diff --git a/chrome/content/vimperator/commandline.js b/chrome/content/vimperator/commandline.js index 40a39f4a..ca2e6d2a 100644 --- a/chrome/content/vimperator/commandline.js +++ b/chrome/content/vimperator/commandline.js @@ -61,26 +61,26 @@ function multiliner(line, prev_match, heredoc) */ function CommandLine () { - //////////////////////////////////////////////////////////////////////////////// - ////////////////////// PRIVATE SECTION ///////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - const UNINITIALIZED = -2; // notifies us, if we need to start history/tab-completion from the beginning - const HISTORY_SIZE = 500; + //////////////////////////////////////////////////////////////////////////////// + ////////////////////// PRIVATE SECTION ///////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + const UNINITIALIZED = -2; // notifies us, if we need to start history/tab-completion from the beginning + const HISTORY_SIZE = 500; - var completionlist = new CompletionList(); - var completions = new Array(); + var completionlist = new CompletionList(); + var completions = new Array(); - var history = new Array(); - var history_index = UNINITIALIZED; - var history_start = ""; + var history = new Array(); + var history_index = UNINITIALIZED; + var history_start = ""; - // 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" + // 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" - var wild_index = 0; // keep track how often we press in a row - var completion_index = UNINITIALIZED; + var wild_index = 0; // keep track how often we press in a row + var completion_index = UNINITIALIZED; // The prompt for the current command, for example : or /. Can be blank var prompt_widget = document.getElementById('new-vim-commandbar-prompt'); @@ -88,341 +88,333 @@ function CommandLine () var command_widget = document.getElementById('new-vim-commandbar'); function setNormalStyle() - { - command_widget.inputField.setAttribute("style","font-family: monospace;"); + { + command_widget.inputField.setAttribute("style","font-family: monospace;"); } function setErrorStyle() - { - command_widget.inputField.setAttribute("style", "font-family: monospace; color:white; background-color:red; font-weight: bold"); + { + command_widget.inputField.setAttribute("style", "font-family: monospace; color:white; background-color:red; font-weight: bold"); } // Sets the prompt - for example, : or / function setPrompt(prompt) - { - if (typeof(prompt) != "string") - prompt = ""; + { + if (typeof(prompt) != "string") + prompt = ""; - prompt_widget.value = prompt; - if (prompt) - { - // Initially (in the xul) the prompt is 'collapsed', this makes - // sure it's visible, then we toggle the display which works better - prompt_widget.style.visibility = 'visible'; - prompt_widget.style.display = 'inline'; - prompt_widget.size = prompt.length; - } - else - { - prompt_widget.style.display = 'none'; - } + prompt_widget.value = prompt; + if (prompt) + { + // Initially (in the xul) the prompt is 'collapsed', this makes + // sure it's visible, then we toggle the display which works better + prompt_widget.style.visibility = 'visible'; + prompt_widget.style.display = 'inline'; + prompt_widget.size = prompt.length; + } + else + { + prompt_widget.style.display = 'none'; + } } // Sets the command - e.g. 'tabopen', 'open http://example.com/' function setCommand(cmd) - { - command_widget.value = cmd; + { + command_widget.value = cmd; } - function addToHistory(str) - { - // first remove all old history elements which have this string - history = history.filter(function(elem) { - return elem != str; + function addToHistory(str) + { + // 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(); - } + // add string to the command line history + if (str.length >= 1 && history.push(str) > HISTORY_SIZE) + history.shift(); + } - //////////////////////////////////////////////////////////////////////////////// - ////////////////////// PUBLIC SECTION ////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////// PUBLIC SECTION ////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// this.getCommand = function() - { - return command_widget.value; + { + return command_widget.value; }; - /** - * All arguments can be ommited and will be defaulted to "" - */ + /** + * All arguments can be ommited and will be defaulted to "" + */ this.open = function(prompt, cmd, minor_mode) - { - if (!prompt) - prompt = ""; - if (!cmd) - cmd = ""; - if (minor_mode) - setCurrentMode(minor_mode); + { + if (!prompt) + prompt = ""; + if (!cmd) + cmd = ""; + if (minor_mode) + setCurrentMode(minor_mode); - setNormalStyle(); - setPrompt(prompt); - setCommand(cmd); - history_index = UNINITIALIZED; - completion_index = UNINITIALIZED; - command_widget.focus(); + setNormalStyle(); + setPrompt(prompt); + setCommand(cmd); + history_index = UNINITIALIZED; + completion_index = UNINITIALIZED; + command_widget.focus(); }; this.echo = function(str) - { - setNormalStyle(); - setPrompt(""); - setCommand(str); + { + setNormalStyle(); + setPrompt(""); + setCommand(str); }; this.echoErr = function(str) - { - setErrorStyle(); - setPrompt(""); - setCommand(str); + { + setErrorStyle(); + setPrompt(""); + setCommand(str); }; this.clear = function() - { - setPrompt(" "); // looks faster than an empty string - setCommand(""); - setNormalStyle(); + { + setPrompt(" "); // looks faster than an empty string + setCommand(""); + setNormalStyle(); }; - this.onEvent = function(event) + this.onEvent = function(event) + { + //var end = false; + var command = this.getCommand(); + + if(event.type == "blur") { - //var end = false; - var command = this.getCommand(); - - if(event.type == "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); - completionlist.hide(); - } - } - else if(event.type == "input") - { - vimperator.triggerCallback("change", command); - } - else if(event.type == "keypress") - { - var key = keyToString(event); - /* user pressed ENTER to carry out a command */ - if (key == "" || key == "" || key == "") - { -// try { -// [prev_match, heredoc, end] = multiliner(command, prev_match, heredoc); -// } catch(e) { -// logObject(e); -// echoerr(e.name + ": " + e.message); -// prev_match = new Array(5); -// heredoc = ''; -// return; -// } -// if (!end) -// command_line.value = ""; - - // the command is saved in the blur() handler - focusContent(); - var res = vimperator.triggerCallback("submit", command); - return res; - } - /* user pressed ESCAPE to cancel this prompt */ - else if (key == "" || key == "") - { - var res = vimperator.triggerCallback("cancel"); - addToHistory(command); - this.clear(); - focusContent(true, true); - return res; - } - - /* user pressed UP or DOWN arrow to cycle history completion */ - else if (key == "" || key == "") - { - //always reset the tab completion if we use up/down keys - completion_index = UNINITIALIZED; - - /* save 'start' position for iterating through the history */ - if (history_index == UNINITIALIZED) - { - history_index = history.length; - history_start = command; - } - - while (history_index >= -1 && history_index <= history.length) - { - key == "" ? history_index-- : history_index++; - if (history_index == history.length) // user pressed DOWN when there is no newer history item - { - setCommand(history_start); - return; - } - // cannot go past history start/end - if (history_index <= -1) - { - history_index = 0; - beep(); - break; - } - if (history_index >= history.length + 1) - { - history_index = history.length; - beep(); - break; - } - - if (history[history_index].indexOf(history_start) == 0) - { - setCommand(history[history_index]); - return; - } - } - beep(); - } - - /* user pressed TAB to get completions of a command */ - else if (key == "" || key == "") - { - //always reset our completion history so up/down keys will start with new values - history_index = UNINITIALIZED; - - // we need to build our completion list first - if (completion_index == UNINITIALIZED) - { - // FIXME: completions.clear(); - completion_start_index = 0; - - completion_index = -1; - wild_index = 0; - - completion_prefix = command.substring(0, command_widget.selectionStart); - completion_postfix = command.substring(command_widget.selectionStart); - var res = vimperator.triggerCallback("complete", completion_prefix); - if (res) - [completion_start_index, completions] = res; - - // Sort the completion list - if (get_pref('wildoptions').match(/\bsort\b/)) - { - completions.sort(function(a, b) { - if (a[0] < b[0]) - return -1; - else if (a[0] > b[0]) - return 1; - else - return 0; - }); - } - } - // we could also return when no completion is found - // but we fall through to the cleanup anyway - if (completions.length == 0) - { - beep(); - // prevent tab from moving to the next field - event.preventDefault(); - event.stopPropagation(); - return; - } - - var wim = get_pref('wildmode').split(/,/); - var has_list = false; - var longest = false; - var full = false; - var wildtype = wim[wild_index++] || wim[wim.length - 1]; - if (wildtype == 'list' || wildtype == 'list:full' || wildtype == 'list:longest') - has_list = true; - else if (wildtype == 'longest' || wildtype == 'list:longest') - longest = true; - else if (wildtype == 'full' || wildtype == 'list:full') - full = true; - - // show the list - if (has_list) - { - completionlist.show(completions); - } - - if (full) - { - if (event.shiftKey) - { - completion_index--; - if(completion_index < -1) - completion_index = completions.length -1; - } - else - { - completion_index++; - if(completion_index >= completions.length) - completion_index = -1; - } - - showStatusbarMessage("match " + (completion_index+1).toString() + " of " + completions.length.toString(), STATUSFIELD_PROGRESS); - // if the list is hidden, this function does nothing - completionlist.selectItem(completion_index); - } - - -// if (longest && completions.length == 1) -// { -// completion_index=0; -// } - - if (completion_index == -1 && !longest) // wrapped around matches, reset command line - { - if (full && completions.length > 1) - { - setCommand(completion_prefix + completion_postfix); - //completion_list.selectedIndex = -1; - } - } - - else - { - if (longest && completions.length > 1) - var compl = get_longest_substring(); - if (full) - var compl = completions[completion_index][0]; - if (completions.length == 1) - var compl = completions[COMMANDS][0]; -//alert(compl) - if (compl) - { - setCommand(command.substring(0, completion_start_index) + compl + completion_postfix); - command_widget.selectionStart = command_widget.selectionEnd = completion_start_index + compl.length; - -// XXX: needed? -// // Start a new completion in the next iteration. Useful for commands like :source -// if (completions.length == 1 && !full) // RFC: perhaps the command can indicate whether the completion should be restarted -// completion_index = UNINITIALIZED; - } - } - - // prevent tab from moving to the next field - event.preventDefault(); - event.stopPropagation(); - } - else if (key == "") - { - // reset the tab completion - completion_index = history_index = UNINITIALIZED; - - // and blur the command line if there is no text left - if(command.length == 0) - { - this.clear(); - focusContent(); - } - } - else // any other key - { - // reset the tab completion - completion_index = history_index = UNINITIALIZED; - } - } + // 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); + completionlist.hide(); + } } + else if(event.type == "input") + { + vimperator.triggerCallback("change", command); + } + else if(event.type == "keypress") + { + var key = keyToString(event); + /* user pressed ENTER to carry out a command */ + if (key == "" || key == "" || key == "") + { + // try { + // [prev_match, heredoc, end] = multiliner(command, prev_match, heredoc); + // } catch(e) { + // logObject(e); + // echoerr(e.name + ": " + e.message); + // prev_match = new Array(5); + // heredoc = ''; + // return; + // } + // if (!end) + // command_line.value = ""; + + // the command is saved in the blur() handler + focusContent(); + var res = vimperator.triggerCallback("submit", command); + return res; + } + /* user pressed ESCAPE to cancel this prompt */ + else if (key == "" || key == "") + { + var res = vimperator.triggerCallback("cancel"); + addToHistory(command); + this.clear(); + focusContent(true, true); + return res; + } + + /* user pressed UP or DOWN arrow to cycle history completion */ + else if (key == "" || key == "") + { + //always reset the tab completion if we use up/down keys + completion_index = UNINITIALIZED; + + /* save 'start' position for iterating through the history */ + if (history_index == UNINITIALIZED) + { + history_index = history.length; + history_start = command; + } + + while (history_index >= -1 && history_index <= history.length) + { + key == "" ? history_index-- : history_index++; + if (history_index == history.length) // user pressed DOWN when there is no newer history item + { + setCommand(history_start); + return; + } + // cannot go past history start/end + if (history_index <= -1) + { + history_index = 0; + beep(); + break; + } + if (history_index >= history.length + 1) + { + history_index = history.length; + beep(); + break; + } + + if (history[history_index].indexOf(history_start) == 0) + { + setCommand(history[history_index]); + return; + } + } + beep(); + } + + /* user pressed TAB to get completions of a command */ + else if (key == "" || key == "") + { + //always reset our completion history so up/down keys will start with new values + history_index = UNINITIALIZED; + + // we need to build our completion list first + if (completion_index == UNINITIALIZED) + { + // FIXME: completions.clear(); + completion_start_index = 0; + + completion_index = -1; + wild_index = 0; + + completion_prefix = command.substring(0, command_widget.selectionStart); + completion_postfix = command.substring(command_widget.selectionStart); + var res = vimperator.triggerCallback("complete", completion_prefix); + if (res) + [completion_start_index, completions] = res; + + // Sort the completion list + if (get_pref('wildoptions').match(/\bsort\b/)) + { + completions.sort(function(a, b) { + if (a[0] < b[0]) + return -1; + else if (a[0] > b[0]) + return 1; + else + return 0; + }); + } + } + // we could also return when no completion is found + // but we fall through to the cleanup anyway + if (completions.length == 0) + { + beep(); + // prevent tab from moving to the next field + event.preventDefault(); + event.stopPropagation(); + return; + } + + var wim = get_pref('wildmode').split(/,/); + var has_list = false; + var longest = false; + var full = false; + var wildtype = wim[wild_index++] || wim[wim.length - 1]; + if (wildtype == 'list' || wildtype == 'list:full' || wildtype == 'list:longest') + has_list = true; + if (wildtype == 'longest' || wildtype == 'list:longest') + longest = true; + else if (wildtype == 'full' || wildtype == 'list:full') + full = true; + + // show the list + if (has_list) + completionlist.show(completions); + + if (full) + { + if (event.shiftKey) + { + completion_index--; + if(completion_index < -1) + completion_index = completions.length -1; + } + else + { + completion_index++; + if(completion_index >= completions.length) + completion_index = -1; + } + + showStatusbarMessage("match " + (completion_index+1).toString() + " of " + completions.length.toString(), STATUSFIELD_PROGRESS); + // if the list is hidden, this function does nothing + completionlist.selectItem(completion_index); + } + + + if (completion_index == -1 && !longest) // wrapped around matches, reset command line + { + if (full && completions.length > 1) + { + setCommand(completion_prefix + completion_postfix); + //completion_list.selectedIndex = -1; + } + } + else + { + if (longest && completions.length > 1) + var compl = get_longest_substring(); + else if (full) + var compl = completions[completion_index][0]; + else if (completions.length == 1) + var compl = completions[0][0]; + if (compl) + { + setCommand(command.substring(0, completion_start_index) + compl + completion_postfix); + command_widget.selectionStart = command_widget.selectionEnd = completion_start_index + compl.length; + + // Start a new completion in the next iteration. Useful for commands like :source + // RFC: perhaps the command can indicate whether the completion should be restarted + // Needed for :source to grab another set of completions after a file/directory has been filled out + if (completions.length == 1 && !full) + completion_index = UNINITIALIZED; + } + } + + // prevent tab from moving to the next field + event.preventDefault(); + event.stopPropagation(); + } + else if (key == "") + { + // reset the tab completion + completion_index = history_index = UNINITIALIZED; + + // and blur the command line if there is no text left + if(command.length == 0) + { + this.clear(); + focusContent(); + } + } + else // any other key + { + // reset the tab completion + completion_index = history_index = UNINITIALIZED; + } + } + } logMessage("CommandLine initialized."); }