diff --git a/content/bookmarks.js b/content/bookmarks.js index 6400625c..477c5e58 100644 --- a/content/bookmarks.js +++ b/content/bookmarks.js @@ -94,6 +94,17 @@ vimperator.Bookmarks = function () //{{{ } } + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// OPTIONS ///////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + vimperator.options.add(["defsearch", "ds"], + "Set the default search engine", + "string", "google"); + vimperator.options.add(["preload"], + "Speed up first time history/bookmark completion", + "boolean", true); + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ diff --git a/content/buffers.js b/content/buffers.js index 47e04a89..c520da75 100644 --- a/content/buffers.js +++ b/content/buffers.js @@ -151,17 +151,52 @@ vimperator.Buffer = function () //{{{ shortHelp: "Test command" } )); - vimperator.options.add(new vimperator.Option(["test"], "boolean", - { - shortHelp: "Test option", - defaultValue: false - } - )); vimperator.mappings.addDefault([vimperator.modes.NORMAL], ["w"], "Test", function () { alert("test"); } ); + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// OPTIONS ///////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + vimperator.options.add(["fullscreen", "fs"], "Show the current window fullscreen", "boolean", false, + { + setter: function (value) { window.fullScreen = value; }, + getter: function () { return window.fullScreen; } + }); + vimperator.options.add(["nextpattern",], + "Patterns to use when guessing the 'next' page in a document sequence", + "stringlist", "\\bnext,^>$,^(>>|»)$,^(>|»),(>|»)$"); + vimperator.options.add(["previouspattern"], + "Patterns to use when guessing the 'previous' page in a document sequence", + "stringlist", "\\bprev|previous\\b,^<$,^(<<|«)$,^(<|«),(<|«)$"); + vimperator.options.add(["pageinfo", "pa"], "Desired info on :pa[geinfo]", "charlist", "gfm", + { + validator: function (value) { return !(/[^gfm]/.test(value) || value.length > 3 || value.length < 1); } + }); + vimperator.options.add(["scroll", "scr"], + "Number of lines to scroll with and commands", + "number", 0, + { + validator: function (value) { return value >= 0; } + } + ); + vimperator.options.add(["showstatuslinks", "ssli"], + "Show the destination of the link under the cursor in the status bar", + "number", 1, + { + validator: function (value) { return (value >= 0 && value <= 2); } + }); + + vimperator.options.add(["usermode", "um"], + "Show current website with a minimal style sheet to make it easily accessible", + "boolean", false, + { + setter: function (value) { getMarkupDocumentViewer().authorStyleDisabled = value; }, + getter: function () { return getMarkupDocumentViewer().authorStyleDisabled; }, + }); + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ diff --git a/content/editor.js b/content/editor.js index c96fb89b..e2a19c4f 100644 --- a/content/editor.js +++ b/content/editor.js @@ -54,6 +54,18 @@ vimperator.Editor = function () //{{{ return ed.controllers.getControllerForCommand("cmd_beginLine"); } + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// OPTIONS ///////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + // + vimperator.options.add(["editor"], + "Set the external text editor", + "string", "gvim -f"); + vimperator.options.add(["insertmode", "im"], + "Use Insert mode as the default for text areas", + "boolean", true); + + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ diff --git a/content/events.js b/content/events.js index ef369992..b806ca35 100644 --- a/content/events.js +++ b/content/events.js @@ -1061,8 +1061,11 @@ vimperator.Events = function () //{{{ tmp.execute(null, vimperator.input.count, key); } } - // only follow a map if there isn't a longer possible mapping (allows you to do :map yy, when y is a mapping) - else if (map && !skipMap && vimperator.mappings.getCandidates(vimperator.mode, candidateCommand).length == 0) + // only follow a map if there isn't a longer possible mapping + // (allows you to do :map z yy, when zz is a longer mapping than z) + // TODO: map.rhs is only defined for user defined commands, should add a "isDefault" property + else if (map && !skipMap && (map.rhs || + vimperator.mappings.getCandidates(vimperator.mode, candidateCommand).length == 0)) { vimperator.input.count = parseInt(countStr, 10); if (isNaN(vimperator.input.count)) @@ -1161,6 +1164,7 @@ vimperator.Events = function () //{{{ return false; }, + // TODO: move to buffer.js? progressListener: { QueryInterface: function (aIID) { diff --git a/content/find.js b/content/find.js index 0051590b..c4040e76 100644 --- a/content/find.js +++ b/content/find.js @@ -109,6 +109,38 @@ vimperator.Search = function () //{{{ searchString = pattern; } + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// OPTIONS ///////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + vimperator.options.add(["hlsearch", "hls"], + "Highlight previous search pattern matches", + "boolean", "false", + { + setter: function (value) + { + if (value) + vimperator.search.highlight(); + else + vimperator.search.clear(); + } + }); + vimperator.options.add(["hlsearchstyle", "hlss"], + "CSS specification of highlighted search items", + "string", "color: black; background-color: yellow; padding: 0; display: inline;"); + vimperator.options.add(["ignorecase", "ic"], + "Ignore case in search patterns", + "boolean", true); + vimperator.options.add(["incsearch", "is"], + "Show where the search pattern matches as it is typed", + "boolean", true); + vimperator.options.add(["linksearch", "lks"], + "Limit the search to hyperlink text", + "boolean", false); + vimperator.options.add(["smartcase", "scs"], + "Override the 'ignorecase' option if the pattern contains uppercase characters", + "boolean", true); + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ @@ -230,9 +262,13 @@ vimperator.Search = function () //{{{ // TODO: code to reposition the document to the place before search started }, + // FIXME: thunderbird incompatible // this is not dependent on the value of 'hlsearch' highlight: function (text) { + if (vimperator.config.name == "Muttator") + return; + // already highlighted? if (window.content.document.getElementsByClassName("__mozilla-findbar-search").length > 0) return; diff --git a/content/hints.js b/content/hints.js index fee05886..177ae600 100644 --- a/content/hints.js +++ b/content/hints.js @@ -391,6 +391,35 @@ vimperator.Hints = function () //{{{ return true; } + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// OPTIONS ///////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + const DEFAULT_HINTTAGS = "//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @class='s'] | " + + "//input[not(@type='hidden')] | //a | //area | //iframe | //textarea | //button | //select | " + + "//xhtml:*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @class='s'] | " + + "//xhtml:input[not(@type='hidden')] | //xhtml:a | //xhtml:area | //xhtml:iframe | //xhtml:textarea | //xhtml:button | //xhtml:select"; + + vimperator.options.add(["extendedhinttags", "eht"], + "XPath string of hintable elements activated by ';'", + "string", DEFAULT_HINTTAGS); + vimperator.options.add(["focusedhintstyle", "fhs"], + "CSS specification of focused hints", + "string", "z-index:5000; font-family:monospace; font-size:12px; color:ButtonText; background-color:ButtonShadow; border-color:ButtonShadow; border-width:1px; border-style:solid; padding:0px 1px 0px 1px; position:absolute;"); + vimperator.options.add(["hintstyle", "hs"], + "CSS specification of unfocused hints", + "string", "z-index:5000; font-family:monospace; font-size:12px; color:white; background-color:red; border-color:ButtonShadow; border-width:0px; border-style:solid; padding:0px 1px 0px 1px; position:absolute;"); + vimperator.options.add(["hinttags", "ht"], + "XPath string of hintable elements activated by 'f' and 'F'", + "string", DEFAULT_HINTTAGS); + vimperator.options.add(["hinttimeout", "hto"], + "Automatically follow non unique numerical hint", + "number", 0, + { + validator: function (value) { return value >= 0; } + }); + + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ diff --git a/content/mappings.js b/content/mappings.js index 03c4a9da..7c8c61a7 100644 --- a/content/mappings.js +++ b/content/mappings.js @@ -376,7 +376,7 @@ vimperator.Mappings = function () //{{{ { shortHelp: "Open help window" } )); addDefaultMap(new vimperator.Map(allModes, ["", ""], - vimperator.events.onEscape, + function () { vimperator.events.onEscape() }, { shortHelp: "Focus content" } )); addDefaultMap(new vimperator.Map(noninsertModes, [":"], diff --git a/content/muttator.js b/content/muttator.js index 2d5c7dff..be243a0d 100644 --- a/content/muttator.js +++ b/content/muttator.js @@ -34,6 +34,7 @@ vimperator.config = { /*** optional options, there are checked for existance and a fallback provided ***/ features: ["mail", "hints"], get mainWidget() { return GetThreadTree(); }, // focusContent() focuses this widget + mainWindowID: "messengerWindow", // used for :set titlestring dialogs: [], guioptions: { m: ["mail-toolbar-menubar2"], T: ["mail-bar2"], f: ["folderPaneBox", "folderpane_splitter"], F: ["folderPaneHeader"] } } diff --git a/content/options.js b/content/options.js index 1ef174d9..f1dce0cb 100644 --- a/content/options.js +++ b/content/options.js @@ -26,7 +26,9 @@ 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.Option = function (names, type, extraInfo) //{{{ +// do NOT create instances of this class yourself, use the helper method +// vimperator.options.add() instead +vimperator.Option = function (names, description, type, defaultValue, getter, setter, validator, completer) { if (!names || !type) return null; @@ -36,30 +38,22 @@ vimperator.Option = function (names, type, extraInfo) //{{{ this.name = names[0]; this.names = names; this.type = type; + this.shortHelp = description || ""; - if (extraInfo) - { - this.shortHelp = extraInfo.shortHelp || null; + // "", 0 are valid default values + this.defaultValue = (defaultValue === undefined) ? null : defaultValue; + value = this.defaultValue; - // "", 0 are valid default values - if (extraInfo.defaultValue !== undefined) - this.defaultValue = extraInfo.defaultValue; - else - this.defaultValue = null; + this.setter = setter || null; + this.getter = getter || null; + this.completer = completer || null; + this.validator = validator || null; - value = this.defaultValue; - - if (extraInfo.setter) - this.setter = extraInfo.setter; - if (extraInfo.getter) - this.getter = extraInfo.getter; - - this.completer = extraInfo.completer || null; - this.validator = extraInfo.validator || null; - } + // this property is set to true whenever the option is first set + // useful to see whether it was changed by some rc file + this.hasChanged = false; // add noOPTION variant of boolean OPTION to this.names - // FIXME: are these variants really considered names? if (this.type == "boolean") { this.names = []; // reset since order is important @@ -70,7 +64,6 @@ vimperator.Option = function (names, type, extraInfo) //{{{ } } - // NOTE: forced defaults need to use vimperator.options.getPref this.__defineGetter__("value", function () { @@ -83,14 +76,12 @@ vimperator.Option = function (names, type, extraInfo) //{{{ function (newValue) { value = newValue; + this.hasChanged = true; if (this.setter) this.setter.call(this, value); } ); - // TODO: add is[Type]() queries for use in set()? - // : add isValid() or just throw an exception? - this.hasName = function (name) { return this.names.some(function (e) { return e == name; }); @@ -108,8 +99,12 @@ vimperator.Option = function (names, type, extraInfo) //{{{ { this.value = this.defaultValue; }; + }; //}}} + + + vimperator.Options = function () //{{{ { //////////////////////////////////////////////////////////////////////////////// @@ -118,21 +113,8 @@ vimperator.Options = function () //{{{ var prefService = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); - var preferences = prefService.getDefaultBranch(""); - var options = []; - // save if we already changed a GUI related option, used for setInitialGUI - var guioptionsDone = false, showtablineDone = false, laststatusDone = false; - - function optionsIterator() - { - for (var i = 0; i < options.length; i++) - yield options[i]; - - throw StopIteration; - } - function storePreference(name, value) { var type = prefService.getPrefType(name); @@ -197,76 +179,6 @@ vimperator.Options = function () //{{{ } } - // show/hide the menubar, toolbar and bookmarks toolbar - function setGuiOptions(value) - { - var guioptions = vimperator.config.guioptions || {}; - try - { - for (let option in guioptions) - guioptions[option].forEach( function(elem) { - document.getElementById(elem).collapsed = (value.indexOf(option.toString()) < 0); }); - } - catch (e) { } - - guioptionsDone = true; - } - - function setLastStatus(value) - { - if (value == 0) - document.getElementById("status-bar").collapsed = true; - else if (value == 1) - vimperator.echo("show status line only with > 1 window not implemented yet"); - else - document.getElementById("status-bar").collapsed = false; - - laststatusDone = true; - } - - function setShowTabline(value) - { - var tabs = getBrowser().mStrip.getElementsByClassName("tabbrowser-tabs")[0]; - if (!tabs) - return; - - if (value == 0) - { - tabs.collapsed = true; - } - else if (value == 1) - { - storePreference("browser.tabs.autoHide", true); - tabs.collapsed = false; - } - else - { - storePreference("browser.tabs.autoHide", false); - tabs.collapsed = false; - } - - showtablineDone = true; - } - - function setTitleString(value) - { - document.getElementById("main-window").setAttribute("titlemodifier", value); - if (window.content.document.title.length > 0) - document.title = window.content.document.title + " - " + value; - else - document.title = value; - } - - function setPopups(value) - { - var values = [ [0, 1], // always in current tab - [0, 3], // in a new tab - [2, 3], // in a new window if it has specified sizes - [1, 2]];// always in new window - storePreference("browser.link.open_newwindow.restriction", values[value][0]); - storePreference("browser.link.open_newwindow", values[value][1]); - } - // // firefox preferences which need to be changed to work well with vimperator // @@ -276,7 +188,8 @@ vimperator.Options = function () //{{{ if (!/keypress/.test(popupAllowedEvents)) storePreference("dom.popup_allowed_events", popupAllowedEvents + " keypress"); - // TODO: shouldn't we be resetting these in destroy() as well? + // TODO: maybe reset in .destroy()? + // TODO: move to vim.js or buffer.js // we have our own typeahead find implementation storePreference("accessibility.typeaheadfind.autostart", false); storePreference("accessibility.typeaheadfind", false); // actually the above setting should do it, but has no effect in firefox @@ -288,11 +201,38 @@ vimperator.Options = function () //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - var optionManager = { + return { __iterator__: function () { - return optionsIterator(); + for (var i = 0; i < options.length; i++) + yield options[i]; + + throw StopIteration; + }, + + add: function (names, description, type, defaultValue, extraInfo) + { + if (!extraInfo) + extraInfo = {}; + + var option = new vimperator.Option(names, description, type, defaultValue, + extraInfo.getter, extraInfo.setter, extraInfo.validator); + + // quickly access options with vimperator.options["wildmode"]: + this.__defineGetter__(option.name, function () { return option.value; }); + this.__defineSetter__(option.name, function (value) { option.value = value; }); + + // TODO: sort option + options.push(option); + }, + + destroy: function () + { + // reset some modified firefox prefs + if (loadPreference("dom.popup_allowed_events", "change click dblclick mouseup reset submit") + == popupAllowedEvents + " keypress") + storePreference("dom.popup_allowed_events", popupAllowedEvents); }, get: function (name) @@ -305,21 +245,6 @@ vimperator.Options = function () //{{{ return null; }, - add: function (option) - { - this.__defineGetter__(option.name, function () { return option.value; }); - this.__defineSetter__(option.name, function (value) { option.value = value; }); - options.push(option); - }, - - destroy: function () - { - // reset some modified firefox prefs - if (loadPreference("dom.popup_allowed_events", "change click dblclick mouseup reset submit") - == popupAllowedEvents + " keypress") - storePreference("dom.popup_allowed_events", popupAllowedEvents); - }, - list: function (onlyNonDefault) { var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + @@ -361,6 +286,21 @@ vimperator.Options = function () //{{{ vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); }, + // TODO: move to vim.js? + // this hack is only needed, because we need to do asynchronous loading of the .vimperatorrc + setInitialGUI: function () + { + if (vimperator.config.name != "Vimperator") + return; + + if (!guioptionsDone) + this.get("guioptions").reset(); + if (!laststatusDone) + this.get("laststatus").reset(); + if (!showtablineDone) + this.get("showtabline").reset(); + }, + listPrefs: function (onlyNonDefault, filter) { if (!filter) @@ -381,7 +321,7 @@ vimperator.Options = function () //{{{ name = prefArray[i]; value = this.getPref(name); if (typeof value == "string") - value = value.substr(0,100).replace(/\n/g, " "); + value = value.substr(0, 100).replace(/\n/g, " "); value = vimperator.util.colorize(value, false); defaultValue = loadPreference(name, null); @@ -403,34 +343,19 @@ vimperator.Options = function () //{{{ vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); }, - // this hack is only needed, because we need to do asynchronous loading of the .vimperatorrc - setInitialGUI: function () - { - if (vimperator.config.name != "Vimperator") - return; - - if (!guioptionsDone) - this.get("guioptions").reset(); - if (!laststatusDone) - this.get("laststatus").reset(); - if (!showtablineDone) - this.get("showtabline").reset(); - }, - - // be better placed in the 'core' vimperator namespace somewhere? - setPref: function (name, value) - { - return storePreference(name, value); - }, - getPref: function (name, forcedDefault) { return loadPreference(name, forcedDefault); }, + setPref: function (name, value) + { + return storePreference(name, value); + }, + resetPref: function (name) { - return preferences.clearUserPref(name); + return prefService.clearUserPref(name); }, // this works only for booleans @@ -441,296 +366,7 @@ vimperator.Options = function () //{{{ else vimperator.echoerr("E488: Trailing characters: " + name + "!"); } - }; - - /////////////////////////////////////////////////////////////////////////////}}} - ////////////////////// DEFAULT OPTIONS ///////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////{{{ - - const DEFAULT_HINTTAGS = "//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @class='s'] | " + - "//input[not(@type='hidden')] | //a | //area | //iframe | //textarea | //button | //select | " + - "//xhtml:*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @class='s'] | " + - "//xhtml:input[not(@type='hidden')] | //xhtml:a | //xhtml:area | //xhtml:iframe | //xhtml:textarea | //xhtml:button | //xhtml:select"; - - optionManager.add(new vimperator.Option(["activate", "act"], "stringlist", - { - shortHelp: "Define when tabs are automatically activated", - defaultValue: "homepage,quickmark,tabopen,paste", - validator: function (value) - { - return value.split(",").every(function (item) { return /^(homepage|quickmark|tabopen|paste|)$/.test(item); }); - } - } - )); - optionManager.add(new vimperator.Option(["complete", "cpt"], "charlist", - { - shortHelp: "Items which are completed at the :[tab]open prompt", - defaultValue: "sfbh", - validator: function (value) { return !/[^sfbh]/.test(value); } - } - )); - optionManager.add(new vimperator.Option(["defsearch", "ds"], "string", - { - shortHelp: "Set the default search engine", - defaultValue: "google" - } - )); - optionManager.add(new vimperator.Option(["editor"], "string", - { - shortHelp: "Set the external text editor", - defaultValue: "gvim -f" - } - )); - optionManager.add(new vimperator.Option(["extendedhinttags", "eht"], "string", - { - shortHelp: "XPath string of hintable elements activated by ';'", - defaultValue: DEFAULT_HINTTAGS - } - )); - optionManager.add(new vimperator.Option(["focusedhintstyle", "fhs"], "string", - { - shortHelp: "CSS specification of focused hints", - defaultValue: "z-index:5000; font-family:monospace; font-size:12px; color:ButtonText; background-color:ButtonShadow; " + - "border-color:ButtonShadow; border-width:1px; border-style:solid; padding:0px 1px 0px 1px; position:absolute;" - } - )); - optionManager.add(new vimperator.Option(["fullscreen", "fs"], "boolean", - { - shortHelp: "Show the current window fullscreen", - setter: function (value) { window.fullScreen = value; }, - getter: function () { return window.fullScreen; }, - defaultValue: false - } - )); - optionManager.add(new vimperator.Option(["guioptions", "go"], "charlist", - { - shortHelp: "Show or hide the menu, toolbar and scrollbars", - setter: function (value) { setGuiOptions(value); }, - defaultValue: "", - validator: function (value) - { - var regex = "[^"; - for (let option in vimperator.config.guioptions) - regex += option.toString(); - - return !(new RegExp(regex + "]").test(value)); - } - } - )); - optionManager.add(new vimperator.Option(["hinttimeout", "hto"], "number", - { - shortHelp: "Automatically follow non unique numerical hint after {arg} ms", - defaultValue: 0, - validator: function (value) { return value >= 0; } - } - )); - optionManager.add(new vimperator.Option(["hintstyle", "hs"], "string", - { - shortHelp: "CSS specification of unfocused hints", - defaultValue: "z-index:5000; font-family:monospace; font-size:12px; color:white; background-color:red; " + - "border-color:ButtonShadow; border-width:0px; border-style:solid; padding:0px 1px 0px 1px; position:absolute;" - } - )); - optionManager.add(new vimperator.Option(["hinttags", "ht"], "string", - { - shortHelp: "XPath string of hintable elements activated by 'f' and 'F'", - defaultValue: DEFAULT_HINTTAGS - } - )); - optionManager.add(new vimperator.Option(["history", "hi"], "number", - { - shortHelp: "Number of Ex commands and search patterns to store in the commandline history", - defaultValue: 500 - } - )); - optionManager.add(new vimperator.Option(["hlsearch", "hls"], "boolean", - { - shortHelp: "Highlight previous search pattern matches", - setter: function (value) { if (value) vimperator.search.highlight(); else vimperator.search.clear(); }, - defaultValue: false - } - )); - optionManager.add(new vimperator.Option(["hlsearchstyle", "hlss"], "string", - { - shortHelp: "CSS specification of highlighted search items", - defaultValue: "color: black; background-color: yellow; padding: 0; display: inline;" - } - )); - optionManager.add(new vimperator.Option(["ignorecase", "ic"], "boolean", - { - shortHelp: "Ignore case in search patterns", - defaultValue: true - } - )); - optionManager.add(new vimperator.Option(["incsearch", "is"], "boolean", - { - shortHelp: "Show where the search pattern matches as it is typed", - defaultValue: true - } - )); - optionManager.add(new vimperator.Option(["insertmode", "im"], "boolean", - { - shortHelp: "Use Insert mode as the default for text areas", - defaultValue: true - } - )); - optionManager.add(new vimperator.Option(["laststatus", "ls"], "number", - { - shortHelp: "Show the status line", - defaultValue: 2, - setter: function (value) { setLastStatus(value); }, - validator: function (value) { return (value >= 0 && value <= 2); } - } - )); - optionManager.add(new vimperator.Option(["linksearch", "lks"], "boolean", - { - shortHelp: "Limit the search to hyperlink text", - defaultValue: false - } - )); - optionManager.add(new vimperator.Option(["more"], "boolean", - { - shortHelp: "Pause the message list window when more than one screen of listings is displayed", - defaultValue: true - } - )); - optionManager.add(new vimperator.Option(["nextpattern"], "stringlist", - { - shortHelp: "Patterns to use when guessing the 'next' page in a document sequence", - defaultValue: "\\bnext,^>$,^(>>|»)$,^(>|»),(>|»)$" - } - )); - optionManager.add(new vimperator.Option(["pageinfo", "pa"], "charlist", - { - shortHelp: "Desired info on :pa[geinfo]", - defaultValue: "gfm", - validator: function (value) { return !(/[^gfm]/.test(value) || value.length > 3 || value.length < 1); } - } - )); - optionManager.add(new vimperator.Option(["popups", "pps"], "number", - { - shortHelp: "Where to show requested popup windows", - defaultValue: 1, - setter: function (value) { setPopups(value); }, - validator: function (value) { return (value >= 0 && value <= 3); } - } - )); - optionManager.add(new vimperator.Option(["preload"], "boolean", - { - shortHelp: "Speed up first time history/bookmark completion", - defaultValue: true - } - )); - optionManager.add(new vimperator.Option(["previewheight", "pvh"], "number", - { - shortHelp: "Default height for preview window", - defaultValue: 10, - validator: function (value) { return (value >= 1 && value <= 50); } - } - )); - optionManager.add(new vimperator.Option(["previouspattern"], "stringlist", - { - shortHelp: "Patterns to use when guessing the 'previous' page in a document sequence", - defaultValue: "\\bprev|previous\\b,^<$,^(<<|«)$,^(<|«),(<|«)$" - } - )); - optionManager.add(new vimperator.Option(["scroll", "scr"], "number", - { - shortHelp: "Number of lines to scroll with C-u and C-d commands", - defaultValue: 0, - validator: function (value) { return value >= 0; } - } - )); - optionManager.add(new vimperator.Option(["showmode", "smd"], "boolean", - { - shortHelp: "Show the current mode in the command line", - defaultValue: true - } - )); - optionManager.add(new vimperator.Option(["showstatuslinks", "ssli"], "number", - { - shortHelp: "Show the destination of the link under the cursor in the status bar", - defaultValue: 1, - validator: function (value) { return (value >= 0 && value <= 2); } - } - )); - optionManager.add(new vimperator.Option(["showtabline", "stal"], "number", - { - shortHelp: "Control when to show the tab bar of opened web pages", - setter: function (value) { setShowTabline(value); }, - defaultValue: 2, - validator: function (value) { return (value >= 0 && value <= 2); } - } - )); - optionManager.add(new vimperator.Option(["smartcase", "scs"], "boolean", - { - shortHelp: "Override the 'ignorecase' option if the pattern contains uppercase characters", - defaultValue: true - } - )); - optionManager.add(new vimperator.Option(["titlestring"], "string", - { - shortHelp: "Change the title of the browser window", - setter: function (value) { setTitleString(value); }, - defaultValue: "Vimperator" - } - )); - optionManager.add(new vimperator.Option(["usermode", "um"], "boolean", - { - shortHelp: "Show current website with a minimal style sheet to make it easily accessible", - setter: function (value) { getMarkupDocumentViewer().authorStyleDisabled = value; }, - getter: function () { return getMarkupDocumentViewer().authorStyleDisabled; }, - defaultValue: false - } - )); - optionManager.add(new vimperator.Option(["verbose", "vbs"], "number", - { - shortHelp: "Define which type of messages are logged", - defaultValue: 0, - validator: function (value) { return (value >= 0 && value <= 9); } - } - )); - optionManager.add(new vimperator.Option(["visualbell", "vb"], "boolean", - { - shortHelp: "Use visual bell instead of beeping on errors", - setter: function (value) { vimperator.options.setPref("accessibility.typeaheadfind.enablesound", !value); }, - defaultValue: false - } - )); - optionManager.add(new vimperator.Option(["wildmode", "wim"], "stringlist", - { - shortHelp: "Define how command line completion works", - defaultValue: "list:full", - validator: function (value) - { - return value.split(",").every(function (item) { return /^(full|longest|list|list:full|list:longest|)$/.test(item); }); - } - } - )); - optionManager.add(new vimperator.Option(["wildoptions", "wop"], "stringlist", - { - shortHelp: "Change how command line completion is done", - defaultValue: "", - validator: function (value) { return /^(sort|)$/.test(value); } - } - )); - //}}} - - // we start with an "empty" GUI so that no toolbars or tabbar is shown if the user - // sets them to empty in the .vimperatorrc, which is sourced asynchronously - if (vimperator.config.name != "Vimperator") - return optionManager; - - setShowTabline(0); - setGuiOptions(""); - setLastStatus(0); - guioptionsDone = showtablineDone = laststatusDone = false; - - setTitleString(optionManager.titlestring); - setPopups(optionManager.popups); - - return optionManager; }; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/tabs.js b/content/tabs.js index dd8a46c4..8488e839 100644 --- a/content/tabs.js +++ b/content/tabs.js @@ -37,6 +37,7 @@ vimperator.Tabs = function () //{{{ //////////////////////////////////////////////////////////////////////////////// ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ + var alternates = [getBrowser().mCurrentTab, null]; // @param spec can either be: // - an absolute integer @@ -72,7 +73,65 @@ vimperator.Tabs = function () //{{{ return position; } - var alternates = [getBrowser().mCurrentTab, null]; + // hide tabs initially + getBrowser().mStrip.getElementsByClassName("tabbrowser-tabs")[0].collapsed = true; + + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// OPTIONS ///////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + vimperator.options.add(["activate", "act"], + "Define when tabs are automatically activated", + "stringlist", "homepage,quickmark,tabopen,paste", + { + validator: function (value) + { + return value.split(",").every(function (item) { return /^(homepage|quickmark|tabopen|paste|)$/.test(item); }); + } + }); + vimperator.options.add(["popups", "pps"], + "Where to show requested popup windows", + "number", 1, + { + setter: function (value) + { + var values = [[0, 1], // always in current tab + [0, 3], // in a new tab + [2, 3], // in a new window if it has specified sizes + [1, 2]];// always in new window + vimperator.options.setPref("browser.link.open_newwindow.restriction", values[value][0]); + vimperator.options.setPref("browser.link.open_newwindow", values[value][1]); + }, + validator: function (value) { return (value >= 0 && value <= 3); } + }); + vimperator.options.add(["showtabline", "stal"], + "Control when to show the tab bar of opened web pages", + "number", 2, + { + setter: function (value) + { + var tabs = getBrowser().mStrip.getElementsByClassName("tabbrowser-tabs")[0]; + if (!tabs) + return; + + if (value == 0) + { + tabs.collapsed = true; + } + else if (value == 1) + { + vimperator.options.setPref("browser.tabs.autoHide", true); + tabs.collapsed = false; + } + else + { + vimperator.options.setPref("browser.tabs.autoHide", false); + tabs.collapsed = false; + } + }, + validator: function (value) { return (value >= 0 && value <= 2); } + }); + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// diff --git a/content/ui.js b/content/ui.js index 2c11b334..40e05084 100644 --- a/content/ui.js +++ b/content/ui.js @@ -236,6 +236,41 @@ vimperator.CommandLine = function () //{{{ multilineInputWidget.setAttribute("rows", lines.toString()); } + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// OPTIONS ///////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + vimperator.options.add(["history", "hi"], + "Number of Ex commands and search patterns to store in the commandline history", + "number", 500); + vimperator.options.add(["more"], + "Pause the message list window when more than one screen of listings is displayed", + "boolean", true); + vimperator.options.add(["complete", "cpt"], + "Items which are completed at the :[tab]open prompt", + "charlist", "sfbh", + { + validator: function (value) { return !/[^sfbh]/.test(value); } + }); + vimperator.options.add(["showmode", "smd"], + "Show the current mode in the command line", + "boolean", true); + vimperator.options.add(["wildmode", "wim"], + "Define how command line completion works", + "stringlist", "list:full", + { + validator: function (value) + { + return value.split(",").every(function (item) { return /^(full|longest|list|list:full|list:longest|)$/.test(item); }); + } + }); + vimperator.options.add(["wildoptions", "wop"], + "Change how command line completion is done", + "stringlist", "", + { + validator: function (value) { return /^(sort|)$/.test(value); } + }); + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ @@ -1071,6 +1106,7 @@ vimperator.StatusLine = function () //{{{ /////////////////////////////////////////////////////////////////////////////{{{ var statusBar = document.getElementById("status-bar"); + statusBar.collapsed = true; // it is later restored unless the user sets laststatus=0 // our status bar fields var statuslineWidget = document.getElementById("vimperator-statusline"); @@ -1080,6 +1116,26 @@ vimperator.StatusLine = function () //{{{ var tabCountWidget = document.getElementById("vimperator-statusline-field-tabcount"); var bufferPositionWidget = document.getElementById("vimperator-statusline-field-bufferposition"); + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// OPTIONS ///////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + vimperator.options.add(["laststatus", "ls"], + "Show the status line", + "number", 2, + { + setter: function (value) + { + if (value == 0) + document.getElementById("status-bar").collapsed = true; + else if (value == 1) + vimperator.echo("show status line only with > 1 window not implemented yet"); + else + document.getElementById("status-bar").collapsed = false; + }, + validator: function (value) { return (value >= 0 && value <= 2); } + }); + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ diff --git a/content/vim.js b/content/vim.js index ba942f38..53825d11 100644 --- a/content/vim.js +++ b/content/vim.js @@ -33,6 +33,93 @@ const vimperator = (function () //{{{ /////////////////////////////////////////////////////////////////////////////{{{ var callbacks = []; + // Only general options are added here, + function addOptions() + { + vimperator.options.add(["guioptions", "go"], + "Show or hide certain GUI elements like the menu or toolbar", + "charlist", "", + { + setter: function (value) + { + var guioptions = vimperator.config.guioptions || {}; + for (let option in guioptions) + { + guioptions[option].forEach( function(elem) + { + try + { + document.getElementById(elem).collapsed = (value.indexOf(option.toString()) < 0); + } + catch (e) { } + }); + } + }, + validator: function (value) + { + var regex = "[^"; + for (let option in vimperator.config.guioptions) + regex += option.toString(); + + return !(new RegExp(regex + "]").test(value)); + } + }); + vimperator.options.add(["titlestring"], // TODO: broken for Thunderbird + "Change the title of the window", + "string", "Vimperator", + { + setter: function (value) + { + try + { + var id = vimperator.config.mainWindowID || "main-window"; + document.getElementById(id).setAttribute("titlemodifier", value); + if (window.content.document.title.length > 0) + document.title = window.content.document.title + " - " + value; + else + document.title = value; + } + catch (e) + { + vimperator.log("Couldn't set titlestring", 1); + } + }, + }); + vimperator.options.add(["verbose", "vbs"], + "Define which type of messages are logged", + "number", 0, + { + validator: function (value) { return (value >= 0 && value <= 9); } + }); + vimperator.options.add(["visualbell", "vb"], + "Use visual bell instead of beeping on errors", + "boolean", false, + { + setter: function (value) { vimperator.options.setPref("accessibility.typeaheadfind.enablesound", !value); }, + }); + } + + // initially hide all GUI, it is later restored unless the user has :set go= or something + // similar in his config + function hideGUI() + { + var guioptions = vimperator.config.guioptions || {}; + for (let option in guioptions) + { + guioptions[option].forEach( function(elem) + { + try + { + document.getElementById(elem).collapsed = true; + } + catch (e) { } + }); + } + +// if (vimperator.has("tabs")) + + } + /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ @@ -48,12 +135,6 @@ const vimperator = (function () //{{{ NEW_BACKGROUND_TAB: 3, NEW_WINDOW: 4, -// config: { -// name: "Vimperator", -// hostApplication: "Firefox", -// dialogs: [] -// }, - // ###VERSION### and ###DATE### are replaced by the Makefile version: "###VERSION### (created: ###DATE###)", @@ -111,7 +192,7 @@ const vimperator = (function () //{{{ } }, - // XXX? move to vimperaotr.util? + // XXX? move to vimperator.util? copyToClipboard: function (str, verbose) { var clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"] @@ -386,11 +467,13 @@ const vimperator = (function () //{{{ // these objects are created here only after the chrome is ready vimperator.log("Loading module options...", 3); - vimperator.options = vimperator.Options(); - vimperator.log("Loading module events...", 3); - vimperator.events = vimperator.Events(); + vimperator.options = vimperator.Options(); addOptions(); vimperator.log("Loading module commands...", 3); vimperator.commands = vimperator.Commands(); + vimperator.log("Loading module mappings...", 3); + vimperator.mappings = vimperator.Mappings(); + vimperator.log("Loading module events...", 3); + vimperator.events = vimperator.Events(); if (vimperator.has("bookmarks")) { vimperator.log("Loading module bookmarks...", 3); @@ -409,8 +492,6 @@ const vimperator = (function () //{{{ vimperator.previewwindow = vimperator.InformationList("vimperator-previewwindow", { incrementalFill: false, maxItems: 10 }); vimperator.log("Loading module buffer window...", 3); vimperator.bufferwindow = vimperator.InformationList("vimperator-bufferwindow", { incrementalFill: false, maxItems: 10 }); - vimperator.log("Loading module mappings...", 3); - vimperator.mappings = vimperator.Mappings(); vimperator.log("Loading module statusline...", 3); vimperator.statusline = vimperator.StatusLine(); vimperator.log("Loading module buffer...", 3); @@ -462,21 +543,20 @@ const vimperator = (function () //{{{ vimperator.registerCallback("complete", vimperator.modes.EX, function (str) { return vimperator.completion.exTabCompletion(str); }); // first time intro message - if (vimperator.options.getPref("extensions.vimperator.firsttime", true)) + if (vimperator.options.getPref("extensions." + vimperator.config.name.toLowerCase() + ".firsttime", true)) { setTimeout(function () { vimperator.commands.help(); - vimperator.options.setPref("extensions.vimperator.firsttime", false); + vimperator.options.setPref("extensions." + vimperator.config.name.toLowerCase() + ".firsttime", false); }, 1000); } - // disable caret browsing initially - //vimperator.options.setFirefoxPref("accessibility.browsewithcaret", false); - //vimperator.focusContent(); - // always start in normal mode vimperator.modes.reset(); + // TODO: we should have some class where all this guioptions stuff fits well + hideGUI(); + // finally, read a ~/.vimperatorrc // make sourcing asynchronous, otherwise commands that open new tabs won't work setTimeout(function () { @@ -514,7 +594,11 @@ const vimperator = (function () //{{{ // after sourcing the initialization files, this function will set // all gui options to their default values, if they have not been // set before by any rc file - vimperator.options.setInitialGUI(); + for (let option in vimperator.options) + { + if (option.setter && !option.hasChanged) + option.reset(); + } }, 0); vimperator.statusline.update();