From 6a04a6e7cfcefa185364d3e26fb69a4148cb2b56 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Wed, 17 Dec 2008 16:41:54 -0500 Subject: [PATCH 01/18] Add 'const service' --- common/content/completion.js | 23 +++-------- common/content/events.js | 15 +++---- common/content/find.js | 4 +- common/content/io.js | 39 +++++++++--------- common/content/liberator.js | 70 ++++++++++++++++++--------------- common/content/options.js | 41 ++++++++++--------- common/content/style.js | 4 +- common/content/tabs.js | 24 +++++------ common/content/ui.js | 5 +-- common/content/util.js | 54 ------------------------- vimperator/content/bookmarks.js | 8 ++-- vimperator/content/config.js | 7 +--- 12 files changed, 108 insertions(+), 186 deletions(-) diff --git a/common/content/completion.js b/common/content/completion.js index bc81887f..be59bb2a 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -526,17 +526,10 @@ function Completion() //{{{ ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - try - { - var completionService = Cc["@mozilla.org/browser/global-history;2"].getService(Ci.nsIAutoCompleteSearch); - } - catch (e) {} - const EVAL_TMP = "__liberator_eval_tmp"; function Javascript() { - let json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON); const OFFSET = 0, CHAR = 1, STATEMENTS = 2, DOTS = 3, FULL_STATEMENTS = 4, COMMA = 5, FUNCTIONS = 6; let stack = []; let functions = []; @@ -1406,7 +1399,7 @@ function Completion() //{{{ location: function location(context) { - if (!completionService) + if (!service.autoCompleteSearch) return context.anchored = false; context.title = ["Smart Completions"]; @@ -1422,8 +1415,8 @@ function Completion() //{{{ for (i in util.range(0, result.matchCount)) ]; }); - completionService.stopSearch(); - completionService.startSearch(context.filter, "", context.result, { + service.autoCompleteSearch.stopSearch(); + service.autoCompleteSearch.startSearch(context.filter, "", context.result, { onSearchResult: function onSearchResult(search, result) { context.result = result; timer.tell(result); @@ -1502,11 +1495,10 @@ function Completion() //{{{ preference: function preference(context) { - let prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); context.anchored = false; context.title = ["Firefox Preference", "Value"]; context.keys = { text: function (item) item, description: function (item) options.getPref(item) }; - context.completions = prefs.getChildList("", { value: 0 }); + context.completions = service.prefs.getChildList("", { value: 0 }); }, search: function search(context, noSuggest) @@ -1553,12 +1545,11 @@ function Completion() //{{{ if (!context.filter) return; - let ss = Cc["@mozilla.org/browser/search-service;1"].getService(Ci.nsIBrowserSearchService); let engineList = (engineAliases || options["suggestengines"] || "google").split(","); let completions = []; engineList.forEach(function (name) { - let engine = ss.getEngineByAlias(name); + let engine = service.browserSearch.getEngineByAlias(name); if (!engine) return; let [,word] = /^\s*(\S+)/.exec(context.filter) || []; @@ -1581,9 +1572,7 @@ function Completion() //{{{ context.title = ["Shell Command", "Path"]; context.generate = function () { - const environmentService = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); - - let dirNames = environmentService.get("PATH").split(RegExp(liberator.has("Win32") ? ";" : ":")); + let dirNames = service.environment.get("PATH").split(RegExp(liberator.has("Win32") ? ";" : ":")); let commands = []; for (let [,dirName] in Iterator(dirNames)) diff --git a/common/content/events.js b/common/content/events.js index 0b66593b..baeca627 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -1541,10 +1541,9 @@ function Events() //{{{ // XXX: function may later be needed to detect a canceled synchronous openURL() onStateChange: function (webProgress, request, flags, status) { - const nsIWebProgressListener = Ci.nsIWebProgressListener; // STATE_IS_DOCUMENT | STATE_IS_WINDOW is important, because we also // receive statechange events for loading images and other parts of the web page - if (flags & (nsIWebProgressListener.STATE_IS_DOCUMENT | nsIWebProgressListener.STATE_IS_WINDOW)) + if (flags & (Ci.nsIWebProgressListener.STATE_IS_DOCUMENT | Ci.nsIWebProgressListener.STATE_IS_WINDOW)) { // This fires when the load event is initiated // only thrown for the current tab, not when another tab changes @@ -1573,12 +1572,11 @@ function Events() //{{{ // for notifying the user about secure web pages onSecurityChange: function (webProgress, aRequest, aState) { - const nsIWebProgressListener = Ci.nsIWebProgressListener; - if (aState & nsIWebProgressListener.STATE_IS_INSECURE) + if (aState & Ci.nsIWebProgressListener.STATE_IS_INSECURE) statusline.setClass("insecure"); - else if (aState & nsIWebProgressListener.STATE_IS_BROKEN) + else if (aState & Ci.nsIWebProgressListener.STATE_IS_BROKEN) statusline.setClass("broken"); - else if (aState & nsIWebProgressListener.STATE_IS_SECURE) + else if (aState & Ci.nsIWebProgressListener.STATE_IS_SECURE) statusline.setClass("secure"); }, onStatusChange: function (webProgress, request, status, message) @@ -1638,9 +1636,8 @@ function Events() //{{{ prefObserver: { register: function () { - const prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService); - this._branch = prefService.getBranch(""); // better way to monitor all changes? - this._branch.QueryInterface(Ci.nsIPrefBranch2); + this._branch = service.pref.getBranch("") // better way to monitor all changes? + .QueryInterface(Ci.nsIPrefBranch2); this._branch.addObserver("", this, false); }, diff --git a/common/content/find.js b/common/content/find.js index b7f9869c..09acc4c2 100644 --- a/common/content/find.js +++ b/common/content/find.js @@ -133,9 +133,7 @@ function Search() //{{{ var highlightObj = { search: function (aWord, matchCase) { - var finder = Cc["@mozilla.org/embedcomp/rangefind;1"] - .createInstance() - .QueryInterface(Ci.nsIFind); + var finder = Cc["@mozilla.org/embedcomp/rangefind;1"].createInstance(Ci.nsIFind); if (matchCase !== undefined) finder.caseSensitive = matchCase; diff --git a/common/content/io.js b/common/content/io.js index 2c30240b..05bceedf 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -61,12 +61,9 @@ function IO() //{{{ const WINDOWS = liberator.has("Win32"); const EXTENSION_NAME = config.name.toLowerCase(); // "vimperator" or "muttator" - const ioService = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService); - const environmentService = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); - const directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); const downloadManager = Cc["@mozilla.org/download-manager;1"].createInstance(Ci.nsIDownloadManager); - var processDir = directoryService.get("CurWorkD", Ci.nsIFile); + var processDir = service.directory.get("CurWorkD", Ci.nsIFile); var cwd = processDir; var oldcwd = null; @@ -74,7 +71,7 @@ function IO() //{{{ var scriptNames = []; // default option values - var cdpath = "," + (environmentService.get("CDPATH").replace(/[:;]/g, ",") || ","); + var cdpath = "," + (service.environment.get("CDPATH").replace(/[:;]/g, ",") || ","); var runtimepath = "~/" + (WINDOWS ? "" : ".") + EXTENSION_NAME; var shell, shellcmdflag; @@ -87,7 +84,7 @@ function IO() //{{{ } else { - shell = environmentService.get("SHELL") || "sh"; + shell = service.environment.get("SHELL") || "sh"; shellcmdflag = "-c"; } @@ -116,13 +113,13 @@ function IO() //{{{ let path = ioManager.getFile(head); try { - path.appendRelativePath(ioManager.expandPath(tail)); // FIXME: should only expand env vars and normalise path separators + path.appendRelativePath(ioManager.expandPath(tail, true)); // FIXME: should only expand env vars and normalise path separators if (path.exists()) path.normalize(); } catch(e) { - return { exists: function () false }; + return { exists: function () false, __noSuchMethod__: function () { throw e } }; } return path; } @@ -131,7 +128,7 @@ function IO() //{{{ { try { - Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile) + service.localFile .initWithPath(path); return true; } @@ -407,7 +404,7 @@ function IO() //{{{ pathSeparator: WINDOWS ? "\\" : "/", - expandPath: function (path) + expandPath: function (path, relative) { // TODO: proper pathname separator translation like Vim - this should be done elsewhere if (WINDOWS) @@ -420,21 +417,21 @@ function IO() //{{{ function expand(path) path.replace( !WINDOWS ? /\$(\w+)\b|\${(\w+)}/g : /\$(\w+)\b|\${(\w+)}|%(\w+)%/g, - function (m, n1, n2, n3) environmentService.get(n1 || n2 || n3) || m + function (m, n1, n2, n3) service.environment.get(n1 || n2 || n3) || m ); path = expand(path); // expand ~ - if ((WINDOWS ? /^~(?:$|\\)/ : /^~(?:$|\/)/).test(path)) + if (!relative && (WINDOWS ? /^~(?:$|\\)/ : /^~(?:$|\/)/).test(path)) { // Try $(VIMPERATOR|MUTTATOR)_HOME || $HOME first, on all systems - let home = environmentService.get(config.name.toUpperCase() + "_HOME") || - environmentService.get("HOME"); + let home = service.environment.get(config.name.toUpperCase() + "_HOME") || + service.environment.get("HOME"); - // Windows has its own ideosynchratic $HOME variables. + // Windows has its own ideosyncratic $HOME variables. if (!home && WINDOWS) - home = environmentService.get("USERPROFILE") || - environmentService.get("HOMEDRIVE") + environmentService.get("HOMEPATH"); + home = service.environment.get("USERPROFILE") || + service.environment.get("HOMEDRIVE") + service.environment.get("HOMEPATH"); path = home + path.substr(1); } @@ -560,7 +557,7 @@ function IO() //{{{ break; } - let file = directoryService.get("TmpD", Ci.nsIFile); + let file = service.directory.get("TmpD", Ci.nsIFile); file.append(tmpName); file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600); @@ -667,7 +664,7 @@ function IO() //{{{ } else { - let dirs = environmentService.get("PATH").split(WINDOWS ? ";" : ":"); + let dirs = service.environment.get("PATH").split(WINDOWS ? ";" : ":"); // Windows tries the cwd first TODO: desirable? if (WINDOWS) dirs = [io.getCurrentDirectory().path].concat(dirs); @@ -685,7 +682,7 @@ lookup: // automatically try to add the executable path extensions on windows if (WINDOWS) { - let extensions = environmentService.get("PATHEXT").split(";"); + let extensions = service.environment.get("PATHEXT").split(";"); for (let [,extension] in Iterator(extensions)) { file = joinPaths(dir, program + extension); @@ -830,7 +827,7 @@ lookup: liberator.echomsg("sourcing " + filename.quote(), 2); let str = ioManager.readFile(file); - let uri = ioService.newFileURI(file); + let uri = service.io.newFileURI(file); // handle pure javascript files specially if (/\.js$/.test(filename)) diff --git a/common/content/liberator.js b/common/content/liberator.js index 6b009c12..8213af0d 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -43,13 +43,33 @@ const userContext = { __proto__: modules }; +let (cc = function (class, meth, iface) { try { return Cc[class][meth](iface) } catch (e) {} }) +{ + const service = { + appStartup: cc("@mozilla.org/toolkit/app-startup;1", "getService", Ci.nsIAppStartup), + autoCompleteSearch: cc("@mozilla.org/browser/global-history;2", "getService", Ci.nsIAutoCompleteSearch), + browserSearch: cc("@mozilla.org/browser/search-service;1", "getService", Ci.nsIBrowserSearchService), + console: cc("@mozilla.org/consoleservice;1", "getService", Ci.nsIConsoleService), + directory: cc("@mozilla.org/file/directory_service;1", "getService", Ci.nsIProperties), + environment: cc("@mozilla.org/process/environment;1", "getService", Ci.nsIEnvironment), + io: cc("@mozilla.org/network/io-service;1", "getService", Ci.nsIIOService).QueryInterface(Ci.nsIIOService2), + json: cc("@mozilla.org/dom/json;1", "createInstance", Ci.nsIJSON), + observer: cc("@mozilla.org/observer-service;1", "getService", Ci.nsIObserverService), + pref: cc("@mozilla.org/preferences-service;1", "getService", Ci.nsIPrefService) + .QueryInterface(Ci.nsIPrefBranch).QueryInterface(nsIPrefBranch2), + sessionStore: cc("@mozilla.org/browser/sessionstore;1", "getService", Ci.nsISessionStore), + subscriptLoader: cc("@mozilla.org/moz/jssubscript-loader;1", "getService", Ci.mozIJSSubScriptLoader), + threadManager: cc("@mozilla.org/thread-manager;1", "getService", Ci.nsIThreadManager), + windowMediator: cc("@mozilla.org/appshell/window-mediator;1", "getService", Ci.nsIWindowMediator), + }; +}; + const liberator = (function () //{{{ { //////////////////////////////////////////////////////////////////////////////// ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); function Runnable(self, func, args) { this.self = self; @@ -678,18 +698,18 @@ const liberator = (function () //{{{ return false; // so you can do: if (...) return liberator.beep(); }, - newThread: function () threadManager.newThread(0), + newThread: function () service.threadManager.newThread(0), callAsync: function (thread, self, func) { - hread = thread || threadManager.newThread(0); + hread = thread || service.threadManager.newThread(0); thread.dispatch(new Runnable(self, func, Array.slice(arguments, 2)), thread.DISPATCH_NORMAL); }, // be sure to call GUI related methods like alert() or dump() ONLY in the main thread callFunctionInThread: function (thread, func) { - thread = thread || threadManager.newThread(0); + thread = thread || service.threadManager.newThread(0); // DISPATCH_SYNC is necessary, otherwise strange things will happen thread.dispatch(new Runnable(null, func, Array.slice(arguments, 2)), thread.DISPATCH_SYNC); @@ -761,8 +781,7 @@ const liberator = (function () //{{{ loadScript: function (uri, context) { - let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader); - loader.loadSubScript(uri, context); + service.subscriptLoader.loadSubScript(uri, context); }, eval: function (str, context) @@ -1047,8 +1066,7 @@ const liberator = (function () //{{{ if (typeof msg == "object") msg = util.objectToString(msg, false); - var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService); - consoleService.logStringMessage(config.name.toLowerCase() + ": " + msg); + service.console.logStringMessage(config.name.toLowerCase() + ": " + msg); }, // open one or more URLs @@ -1085,7 +1103,6 @@ const liberator = (function () //{{{ { let url = Array.concat(urls)[0]; let postdata = Array.concat(urls)[1]; - let whichwindow = window; // decide where to load the first url switch (where) @@ -1105,10 +1122,9 @@ const liberator = (function () //{{{ break; case liberator.NEW_WINDOW: - const wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); window.open(); - whichwindow = wm.getMostRecentWindow("navigator:browser"); - whichwindow.loadURI(url, null, postdata); + service.windowMediator.getMostRecentWindow("navigator:browser") + .loadURI(url, null, postdata); break; default: @@ -1150,11 +1166,8 @@ const liberator = (function () //{{{ else options.setPref("browser.startup.page", 1); // start with default homepage session - const nsIAppStartup = Ci.nsIAppStartup; if (force) - Cc["@mozilla.org/toolkit/app-startup;1"] - .getService(nsIAppStartup) - .quit(nsIAppStartup.eForceQuit); + service.appStartup.quit(Ci.nsIAppStartup.eForceQuit); else window.goQuitApplication(); }, @@ -1182,32 +1195,26 @@ const liberator = (function () //{{{ restart: function () { - const nsIAppStartup = Ci.nsIAppStartup; - // notify all windows that an application quit has been requested. - var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); - os.notifyObservers(cancelQuit, "quit-application-requested", null); + service.observer.notifyObservers(cancelQuit, "quit-application-requested", null); // something aborted the quit process. if (cancelQuit.data) return; // notify all windows that an application quit has been granted. - os.notifyObservers(null, "quit-application-granted", null); + service.observer.notifyObservers(null, "quit-application-granted", null); // enumerate all windows and call shutdown handlers - var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); - var windows = wm.getEnumerator(null); + var windows = service.windowMediator.getEnumerator(null); while (windows.hasMoreElements()) { var win = windows.getNext(); if (("tryToClose" in win) && !win.tryToClose()) return; } - Cc["@mozilla.org/toolkit/app-startup;1"] - .getService(nsIAppStartup) - .quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit); + service.appStartup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit); }, // TODO: move to {muttator,vimperator,...}.js @@ -1324,7 +1331,7 @@ const liberator = (function () //{{{ sleep: function (delay) { - let mainThread = threadManager.mainThread; + let mainThread = service.threadManager.mainThread; let end = Date.now() + delay; while (Date.now() < end) @@ -1334,8 +1341,8 @@ const liberator = (function () //{{{ callInMainThread: function (callback, self) { - let mainThread = threadManager.mainThread; - if (!threadManager.isMainThread) + let mainThread = service.threadManager.mainThread; + if (!service.threadManager.isMainThread) mainThread.dispatch({ run: callback.call(self) }, mainThread.DISPATCH_NORMAL); else callback.call(self); @@ -1343,7 +1350,7 @@ const liberator = (function () //{{{ threadYield: function (flush, interruptable) { - let mainThread = threadManager.mainThread; + let mainThread = service.threadManager.mainThread; liberator.interrupted = false; do { @@ -1382,9 +1389,8 @@ const liberator = (function () //{{{ get windows() { - var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); var wa = []; - var enumerator = wm.getEnumerator("navigator:browser"); + var enumerator = service.windowMediator.getEnumerator("navigator:browser"); while (enumerator.hasMoreElements()) wa.push(enumerator.getNext()); return wa; diff --git a/common/content/options.js b/common/content/options.js index 34828e18..3ae0e576 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -301,7 +301,6 @@ function Options() //{{{ const SAVED = "liberator.saved."; - const prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); var optionHash = {}; function optionObserver(key, event, option) @@ -320,27 +319,27 @@ function Options() //{{{ function storePreference(name, value) { - var type = prefService.getPrefType(name); + var type = service.prefBranch.getPrefType(name); switch (typeof value) { case "string": - if (type == prefService.PREF_INVALID || type == prefService.PREF_STRING) - prefService.setCharPref(name, value); - else if (type == prefService.PREF_INT) + if (type == service.prefBranch.PREF_INVALID || type == service.prefBranch.PREF_STRING) + service.pref.setCharPref(name, value); + else if (type == service.pref.PREF_INT) liberator.echoerr("E521: Number required after =: " + name + "=" + value); else liberator.echoerr("E474: Invalid argument: " + name + "=" + value); break; case "number": - if (type == prefService.PREF_INVALID || type == prefService.PREF_INT) - prefService.setIntPref(name, value); + if (type == service.pref.PREF_INVALID || type == service.pref.PREF_INT) + service.pref.setIntPref(name, value); else liberator.echoerr("E474: Invalid argument: " + name + "=" + value); break; case "boolean": - if (type == prefService.PREF_INVALID || type == prefService.PREF_BOOL) - prefService.setBoolPref(name, value); - else if (type == prefService.PREF_INT) + if (type == service.pref.PREF_INVALID || type == service.pref.PREF_BOOL) + service.pref.setBoolPref(name, value); + else if (type == service.pref.PREF_INT) liberator.echoerr("E521: Number required after =: " + name + "=" + value); else liberator.echoerr("E474: Invalid argument: " + name + "=" + value); @@ -356,22 +355,22 @@ function Options() //{{{ if (forcedDefault != null) // this argument sets defaults for non-user settable options (like extensions.history.comp_history) defaultValue = forcedDefault; - let branch = defaultBranch ? prefService.getDefaultBranch("") : prefService; - let type = prefService.getPrefType(name); + let branch = defaultBranch ? service.pref.getDefaultBranch("") : service.pref; + let type = service.pref.getPrefType(name); try { switch (type) { - case prefService.PREF_STRING: + case service.pref.PREF_STRING: let value = branch.getComplexValue(name, Ci.nsISupportsString).data; // try in case it's a localized string (will throw an exception if not) - if (!prefService.prefIsLocked(name) && !prefService.prefHasUserValue(name) && + if (!service.pref.prefIsLocked(name) && !service.pref.prefHasUserValue(name) && /^chrome:\/\/.+\/locale\/.+\.properties/.test(value)) value = branch.getComplexValue(name, Ci.nsIPrefLocalizedString).data; return value; - case prefService.PREF_INT: + case service.pref.PREF_INT: return branch.getIntPref(name); - case prefService.PREF_BOOL: + case service.pref.PREF_BOOL: return branch.getBoolPref(name); default: return defaultValue; @@ -777,7 +776,7 @@ function Options() //{{{ { completion.setFunctionCompleter(options.get, [function () ([o.name, o.description] for (o in options))]); completion.setFunctionCompleter([options.getPref, options.safeSetPref, options.setPref, options.resetPref, options.invertPref], - [function () Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch) + [function () service.prefBranch .getChildList("", { value: 0 }) .map(function (pref) [pref, ""])]); }); @@ -880,12 +879,12 @@ function Options() //{{{ if (!filter) filter = ""; - var prefArray = prefService.getChildList("", { value: 0 }); + var prefArray = service.pref.getChildList("", { value: 0 }); prefArray.sort(); let prefs = function () { for each (let pref in prefArray) { - let userValue = prefService.prefHasUserValue(pref); + let userValue = service.pref.prefHasUserValue(pref); if (onlyNonDefault && !userValue || pref.indexOf(filter) == -1) continue; @@ -978,13 +977,13 @@ function Options() //{{{ resetPref: function (name) { - return prefService.clearUserPref(name); + return service.pref.clearUserPref(name); }, // this works only for booleans invertPref: function (name) { - if (prefService.getPrefType(name) == prefService.PREF_BOOL) + if (service.pref.getPrefType(name) == service.pref.PREF_BOOL) this.setPref(name, !this.getPref(name)); else liberator.echoerr("E488: Trailing characters: " + name + "!"); diff --git a/common/content/style.js b/common/content/style.js index ea4b5533..da30349e 100644 --- a/common/content/style.js +++ b/common/content/style.js @@ -212,8 +212,8 @@ function Styles(name, store, serial) const util = modules.util; const sleep = liberator.sleep; const storage = modules.storage; - const consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService); - const ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + const consoleService = service.console; + const ios = service.io; const sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); const namespace = '@namespace html "' + XHTML + '";\n' + '@namespace xul "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";\n' + diff --git a/common/content/tabs.js b/common/content/tabs.js index 93ac3ca9..0635705d 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -97,13 +97,11 @@ function Tabs() //{{{ function copyTab(to, from) { - const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - if (!from) from = getBrowser().mTabContainer.selectedItem; - let tabState = ss.getTabState(from); - ss.setTabState(to, tabState); + let tabState = service.sessionStore.getTabState(from); + service.sessionStore.setTabState(to, tabState); } // hide tabs initially @@ -263,12 +261,12 @@ function Tabs() //{{{ mappings.add([modes.NORMAL], ["d"], "Delete current buffer", - function (count) { tabs.remove(getBrowser().mCurrentTab, count, false, 0); }, + function (count) { tabs.remove(tabs.getTab(), count, false, 0); }, { flags: Mappings.flags.COUNT }); mappings.add([modes.NORMAL], ["D"], "Delete current buffer, focus tab to the left", - function (count) { tabs.remove(getBrowser().mCurrentTab, count, true, 0); }, + function (count) { tabs.remove(tabs.getTab(), count, true, 0); }, { flags: Mappings.flags.COUNT }); mappings.add([modes.NORMAL], ["gb"], @@ -345,7 +343,7 @@ function Tabs() //{{{ liberator.echoerr("E94: No matching tab for " + arg); } else // just remove the current tab - tabs.remove(getBrowser().mCurrentTab, count > 0 ? count : 1, special, 0); + tabs.remove(tabs.getTab(), count > 0 ? count : 1, special, 0); }, { argCount: "?", @@ -733,14 +731,12 @@ function Tabs() //{{{ if (index != undefined) return getBrowser().mTabs[index]; - return getBrowser().mTabContainer.selectedItem; + return getBrowser().mCurrentTab; }, get closedTabs() { - const json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON); - const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - return json.decode(ss.getClosedTabData(window)); + return service.json.decode(service.sessionStore.getClosedTabData(window)); }, list: function (filter) @@ -843,8 +839,7 @@ function Tabs() //{{{ { if (bypassCache) { - const nsIWebNavigation = Ci.nsIWebNavigation; - const flags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE; + const flags = Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE; getBrowser().getBrowserForTab(tab).reloadWithFlags(flags); } else @@ -968,8 +963,7 @@ function Tabs() //{{{ tab = getBrowser().mTabContainer.selectedItem; window.open(); - const wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); - let win = wm.getMostRecentWindow("navigator:browser"); + let win = service.windowMediator.getMostRecentWindow("navigator:browser"); copyTab(win.getBrowser().mCurrentTab, tab); this.remove(tab, 1, false, 1); diff --git a/common/content/ui.js b/common/content/ui.js index 328ce866..b7cdc151 100644 --- a/common/content/ui.js +++ b/common/content/ui.js @@ -659,9 +659,8 @@ function CommandLine() //{{{ { completer: function completer(value) { - let ss = Cc["@mozilla.org/browser/search-service;1"].getService(Ci.nsIBrowserSearchService); - let engines = ss.getEngines({}) - .filter(function (engine) engine.supportsResponseType("application/x-suggestions+json")); + let engines = service.browserSearch.getEngines({}) + .filter(function (engine) engine.supportsResponseType("application/x-suggestions+json")); return engines.map(function (engine) [engine.alias, engine.description]); }, diff --git a/common/content/util.js b/common/content/util.js index d6499e57..bf7e7e88 100644 --- a/common/content/util.js +++ b/common/content/util.js @@ -81,60 +81,6 @@ const util = { //{{{ } }, - // TODO: class could have better variable names/documentation - Timer: function Timer(minInterval, maxInterval, callback) - { - let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this.doneAt = 0; - this.latest = 0; - this.notify = function (aTimer) - { - timer.cancel(); - this.latest = 0; - /* minInterval is the time between the completion of the command and the next firing. */ - this.doneAt = Date.now() + minInterval; - - try - { - callback(this.arg); - } - finally - { - this.doneAt = Date.now() + minInterval; - } - }; - this.tell = function (arg) - { - if (arg !== undefined) - this.arg = arg; - - let now = Date.now(); - if (this.doneAt == -1) - timer.cancel(); - - let timeout = minInterval; - if (now > this.doneAt && this.doneAt > -1) - timeout = 0; - else if (this.latest) - timeout = Math.min(timeout, this.latest - now); - else - this.latest = now + maxInterval; - - timer.initWithCallback(this, Math.max(timeout, 0), timer.TYPE_ONE_SHOT); - this.doneAt = -1; - }; - this.reset = function () - { - timer.cancel(); - this.doneAt = 0; - }; - this.flush = function () - { - if (this.latest) - this.notify(); - }; - }, - cloneObject: function cloneObject(obj) { if (obj instanceof Array) diff --git a/vimperator/content/bookmarks.js b/vimperator/content/bookmarks.js index fbcd419f..5f5e73d4 100644 --- a/vimperator/content/bookmarks.js +++ b/vimperator/content/bookmarks.js @@ -40,8 +40,8 @@ function Bookmarks() //{{{ const historyService = PlacesUtils.history; const bookmarksService = PlacesUtils.bookmarks; const taggingService = PlacesUtils.tagging; - const searchService = Cc["@mozilla.org/browser/search-service;1"].getService(Ci.nsIBrowserSearchService); - const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + const searchService = service.browserSearch; + const ioService = service.io; const faviconService = Cc["@mozilla.org/browser/favicon-service;1"].getService(Ci.nsIFaviconService); const Bookmark = new Struct("url", "title", "icon", "keyword", "tags", "id"); @@ -533,7 +533,7 @@ function Bookmarks() //{{{ getSuggestions: function getSuggestions(engine, query, callback) { - let ss = Cc["@mozilla.org/browser/search-service;1"].getService(Ci.nsIBrowserSearchService); + let ss = service.browserSearch; const responseType = "application/x-suggestions+json"; let engine = ss.getEngineByAlias(engine); @@ -544,7 +544,7 @@ function Bookmarks() //{{{ function process(resp) { - const json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON); + const json = service.json; let results = []; try { diff --git a/vimperator/content/config.js b/vimperator/content/config.js index a11c8e2c..5214472e 100644 --- a/vimperator/content/config.js +++ b/vimperator/content/config.js @@ -418,16 +418,13 @@ const config = { //{{{ { setter: function (value) { - const ioService = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService2); - ioService.offline = !value; - gPrefService.setBoolPref("browser.offline", ioService.offline); - + gPrefService.setBoolPref("browser.offline", service.io.offline); return value; }, getter: function () { - return Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService2).offline; + return service.io.offline; } }); From 80672176a0d4a7a623ca6ef590abbbb2d37a51d0 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sat, 20 Dec 2008 21:44:27 +1100 Subject: [PATCH 02/18] remove unused variable in :set completer --- common/content/options.js | 1 - 1 file changed, 1 deletion(-) diff --git a/common/content/options.js b/common/content/options.js index a1844a5f..3ff2e499 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -685,7 +685,6 @@ function Options() //{{{ completer: function (context, args, modifiers) { let filter = context.filter; - var optionCompletions = []; if (args.bang) // list completions for about:config entries { From 29817b5d72e0b27e669e1112e6db95480427b129 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sun, 21 Dec 2008 00:11:30 +1100 Subject: [PATCH 03/18] add NEWS item about new option value quoting requirement --- vimperator/NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/vimperator/NEWS b/vimperator/NEWS index f982feda..4fd0ddaf 100644 --- a/vimperator/NEWS +++ b/vimperator/NEWS @@ -20,6 +20,7 @@ * IMPORTANT: renamed Startup and Quit autocmd events to VimperatorEnter and VimperatorLeave respectively * IMPORTANT: 'verbose' is now by default at 1, set to 0 to not show any status messages + * IMPORTANT: option values containing whitespace must now be quoted E.g. :set editor=gvim\ -f * :hardcopy now supports output redirection to a file on Unix and MacUnix * add ";f" extended hint mode to focus a frame From 5b4a1d11f8abcd3a7fd469b03f925b23398f85e9 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sun, 21 Dec 2008 00:28:19 +1100 Subject: [PATCH 04/18] prefer let over var in Mappings, Modes, and Options --- common/content/mappings.js | 14 +++++++------- common/content/modes.js | 6 +++--- common/content/options.js | 32 ++++++++++++++++---------------- common/content/ui.js | 2 +- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/common/content/mappings.js b/common/content/mappings.js index d409ba79..d47501b3 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -59,7 +59,7 @@ Map.prototype = { execute: function (motion, count, argument) { - var args = []; + let args = []; if (this.flags & Mappings.flags.MOTION) args.push(motion); @@ -98,7 +98,7 @@ function Mappings() //{{{ function addMap(map, userMap) { - var where = userMap ? user : main; + let where = userMap ? user : main; map.modes.forEach(function (mode) { if (!(mode in where)) where[mode] = []; @@ -108,7 +108,7 @@ function Mappings() //{{{ function getMap(mode, cmd, stack) { - var maps = stack[mode] || []; + let maps = stack[mode] || []; for (let [,map] in Iterator(maps)) { @@ -121,8 +121,8 @@ function Mappings() //{{{ function removeMap(mode, cmd) { - var maps = user[mode] || []; - var names; + let maps = user[mode] || []; + let names; for (let [i, map] in Iterator(maps)) { @@ -305,7 +305,7 @@ function Mappings() //{{{ addUserMap: function (modes, keys, description, action, extra) { keys = keys.map(expandLeader); - var map = new Map(modes, keys, description || "User defined mapping", action, extra); + let map = new Map(modes, keys, description || "User defined mapping", action, extra); // remove all old mappings to this key sequence for (let [,name] in Iterator(map.names)) @@ -353,7 +353,7 @@ function Mappings() //{{{ getMapLeader: function () { - var leaderRef = liberator.variableReference("mapleader"); + let leaderRef = liberator.variableReference("mapleader"); return leaderRef[0] ? leaderRef[0][leaderRef[1]] : "\\"; }, diff --git a/common/content/modes.js b/common/content/modes.js index e79a67f4..fc4195c5 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -54,13 +54,13 @@ const modes = (function () //{{{ return "-- PASS THROUGH --"; // when recording a macro - var macromode = ""; + let macromode = ""; if (modes.isRecording) macromode = "recording"; else if (modes.isReplaying) macromode = "replaying"; - var ext = ""; + let ext = ""; if (extended & modes.MENU) // TODO: desirable? ext += " (menu)"; ext += " --" + macromode; @@ -199,7 +199,7 @@ const modes = (function () //{{{ pop: function (silent) { - var a = modeStack.pop(); + let a = modeStack.pop(); if (a) this.set(a[0], a[1], silent); else diff --git a/common/content/options.js b/common/content/options.js index 3ff2e499..0a244ab3 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -117,7 +117,7 @@ Option.prototype = { scope = this.scope; } - var aValue; + let aValue; if (liberator.has("tabs") && (scope & options.OPTION_SCOPE_LOCAL)) aValue = tabs.options[this.name]; @@ -334,7 +334,7 @@ function Options() //{{{ prefContexts[prefContexts.length - 1][name] = val; } - var type = prefService.getPrefType(name); + let type = prefService.getPrefType(name); switch (typeof value) { case "string": @@ -439,7 +439,7 @@ function Options() //{{{ if (!args) { - var str = + let str = { template.map(liberator.globalVariables, function ([i, value]) { @@ -460,20 +460,20 @@ function Options() //{{{ return; } - var matches; + let matches; // 1 - type, 2 - name, 3 - +-., 4 - expr if (matches = args.match(/([$@&])?([\w:]+)\s*([-+.])?=\s*(.+)/)) { if (!matches[1]) { - var reference = liberator.variableReference(matches[2]); + let reference = liberator.variableReference(matches[2]); if (!reference[0] && matches[3]) { liberator.echoerr("E121: Undefined variable: " + matches[2]); return; } - var expr = liberator.evalExpression(matches[4]); + let expr = liberator.evalExpression(matches[4]); if (expr === undefined) { liberator.echoerr("E15: Invalid expression: " + matches[4]); @@ -506,14 +506,14 @@ function Options() //{{{ // 1 - name else if (matches = args.match(/^\s*([\w:]+)\s*$/)) { - var reference = liberator.variableReference(matches[1]); + let reference = liberator.variableReference(matches[1]); if (!reference[0]) { liberator.echoerr("E121: Undefined variable: " + matches[1]); return; } - var value = reference[0][reference[1]]; + let value = reference[0][reference[1]]; let prefix = typeof value == "number" ? "#" : typeof value == "function" ? "*" : " "; @@ -567,9 +567,9 @@ function Options() //{{{ { if (bang) { - var onlyNonDefault = false; - var reset = false; - var invertBoolean = false; + let onlyNonDefault = false; + let reset = false; + let invertBoolean = false; if (args[0] == "") { @@ -757,15 +757,15 @@ function Options() //{{{ "Delete a variable", function (args) { - //var names = args.split(/ /); + //let names = args.split(/ /); //if (typeof names == "string") names = [names]; - //var length = names.length; + //let length = names.length; //for (let i = 0, name = names[i]; i < length; name = names[++i]) for (let [,name] in args) { - var name = args[i]; - var reference = liberator.variableReference(name); + let name = args[i]; + let reference = liberator.variableReference(name); if (!reference[0]) { if (!args.bang) @@ -893,7 +893,7 @@ function Options() //{{{ if (!filter) filter = ""; - var prefArray = prefService.getChildList("", { value: 0 }); + let prefArray = prefService.getChildList("", { value: 0 }); prefArray.sort(); let prefs = function () { for each (let pref in prefArray) diff --git a/common/content/ui.js b/common/content/ui.js index 5cd2cc92..992fe308 100644 --- a/common/content/ui.js +++ b/common/content/ui.js @@ -810,7 +810,7 @@ function CommandLine() //{{{ command.description, function (args) { - var str = echoArgumentToString(args.string, true); + let str = echoArgumentToString(args.string, true); if (str != null) command.action(str); }, From 99ff01aac1f4795f13aaaff95e091009f6d3dcf5 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 11:07:40 -0500 Subject: [PATCH 05/18] Revert "add NEWS item about new option value quoting requirement" It's already there. This reverts commit 87418ed064951f83690bb02442bf4a4de2c2a8db. --- vimperator/NEWS | 1 - 1 file changed, 1 deletion(-) diff --git a/vimperator/NEWS b/vimperator/NEWS index 4fd0ddaf..f982feda 100644 --- a/vimperator/NEWS +++ b/vimperator/NEWS @@ -20,7 +20,6 @@ * IMPORTANT: renamed Startup and Quit autocmd events to VimperatorEnter and VimperatorLeave respectively * IMPORTANT: 'verbose' is now by default at 1, set to 0 to not show any status messages - * IMPORTANT: option values containing whitespace must now be quoted E.g. :set editor=gvim\ -f * :hardcopy now supports output redirection to a file on Unix and MacUnix * add ";f" extended hint mode to focus a frame From 911470e0a76c333a4ad89430dddef089f506a80d Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 13:30:08 -0500 Subject: [PATCH 06/18] Speed up file completion a bit, with sorting off. Sort directories first, which slows it down with sorting on. --- common/content/completion.js | 53 ++++++++++++++++++------------------ common/content/io.js | 3 +- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/common/content/completion.js b/common/content/completion.js index 7eee6591..f05dd141 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -327,7 +327,7 @@ CompletionContext.prototype = { this.itemCache = {}; this.cache.offset = this.offset; if (!this.itemCache[this.key]) - this.itemCache[this.key] = this._generate.call(this); + this.itemCache[this.key] = this._generate.call(this) || []; return this.itemCache[this.key]; }, set generate(arg) @@ -1384,7 +1384,7 @@ function Completion() //{{{ io.getRuntimeDirectories("colors").forEach(function (dir) { context.fork(dir.path, 0, null, function (context) { context.filter = dir.path + io.pathSeparator + context.filter; - completion.file(context, true); + completion.file(context); context.title = ["Color Scheme"]; context.quote = ["", function (text) text.replace(/\.vimp$/, ""), ""]; }); @@ -1404,10 +1404,10 @@ function Completion() //{{{ context.completions = config.dialogs; }, - directory: function directory(context, tail) + directory: function directory(context, full) { - this.file(context, tail); - context.filters.push(function (item) this.getKey(item, "description") == "Directory"); + this.file(context, full); + context.filters.push(function ({ item: f }) f.isDirectory()); }, environment: function environment(context) @@ -1468,40 +1468,39 @@ function Completion() //{{{ // TODO: support file:// and \ or / path separators on both platforms // if "tail" is true, only return names without any directory components - file: function file(context, tail) + file: function file(context, full) { - let [dir] = context.filter.match(/^(?:.*[\/\\])?/); // dir == "" is expanded inside readDirectory to the current dir + let [dir] = context.filter.match(/^(?:.*[\/\\])?/); - context.title = ["Path", "Type"]; - if (tail) + if (!full) context.advance(dir.length); - context.keys = { text: 0, description: 1, icon: 2 }; + + context.title = [full ? "Path" : "Filename", "Type"]; + context.keys = { + text: !full ? "leafName" : function (f) dir + f.leafName, + description: function (f) f.isDirectory() ? "Directory" : "File", + icon: function (f) f.isDirectory() ? "resource://gre/res/html/folder.png" + : "moz-icon://" + f.leafName + }; + context.compare = function ({ item: a }, { item: b }) + b.isDirectory() - a.isDirectory() || String.localeCompare(a.path, b.path); + + if (options["wildignore"]) + { + let wigRegexp = RegExp("(^" + options.get("wildignore").values.join("|") + ")$"); + context.filters.push(function ({item: f}) f.isDirectory() || !wigRegexp.test(f.leafName)); + } + // context.background = true; context.key = dir; context.generate = function generate_file() { - context.cache.dir = dir; - try { - let files = io.readDirectory(dir); - - if (options["wildignore"]) - { - let wigRegexp = RegExp("(^" + options["wildignore"].replace(",", "|", "g") + ")$"); - files = files.filter(function (f) f.isDirectory() || !wigRegexp.test(f.leafName)) - } - - return files.map( - function (file) [tail ? file.leafName : dir + file.leafName, - file.isDirectory() ? "Directory" : "File", - file.isDirectory() ? "resource://gre/res/html/folder.png" - : "moz-icon://" + file.leafName] - ); + return io.readDirectory(dir); } catch (e) {} - return []; }; }, diff --git a/common/content/io.js b/common/content/io.js index 28b2d97f..227c5568 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -589,8 +589,7 @@ function IO() //{{{ while (entries.hasMoreElements()) { let entry = entries.getNext(); - entry.QueryInterface(Ci.nsIFile); - array.push(entry); + array.push(entry.QueryInterface(Ci.nsIFile)); } if (sort) return array.sort(function (a, b) b.isDirectory() - a.isDirectory() || String.localeCompare(a.path, b.path)); From 653893bbfca63135c69fd5792cac2b1b6f1d45ae Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 13:49:18 -0500 Subject: [PATCH 07/18] Speed up file completion sorting, remove need for CompletionContextliberator.jsgetKey --- common/content/completion.js | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/common/content/completion.js b/common/content/completion.js index f05dd141..be606b99 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -318,6 +318,22 @@ CompletionContext.prototype = { get message() this._message || (this.waitingForTab ? "Waiting for " : null), set message(val) this._message = val, + get proto() + { + let res = {}; + for (let i in Iterator(this.keys)) + { + let [k, v] = i; + let _k = "_" + k; + if (typeof v == "function") + res.__defineGetter__(k, function () _k in this ? this[_k] : (this[_k] = v(this.item))); + else + res.__defineGetter__(k, function () _k in this ? this[_k] : (this[_k] = this.item[v])); + res.__defineSetter__(k, function (val) this[_k] = val); + } + return res; + }, + get regenerate() this._generate && (!this.completions || !this.itemCache[this.key] || this.cache.offset != this.offset), set regenerate(val) { if (val) delete this.itemCache[this.key] }, @@ -404,7 +420,8 @@ CompletionContext.prototype = { let self = this; delete this._substrings; - let filtered = this.filterFunc(items.map(function (item) ({ text: self.getKey({ item: item }, "text"), item: item }))); + let proto = this.proto; + let filtered = this.filterFunc(items.map(function (item) ({ __proto__: proto, item: item }))); if (this.maxItems) filtered = filtered.slice(0, this.maxItems); @@ -1334,9 +1351,9 @@ function Completion() //{{{ context.format = bookmarks.format; for (let val in Iterator(extra || [])) { - let [k, v] = val; // Need let block here for closure. + let [k, v] = val; // Need block scope here for the closure if (v) - context.filters.push(function (item) this._match(v, this.getKey(item, k))); + context.filters.push(function (item) this._match(v, item[k])); } // Need to make a copy because set completions() checks instanceof Array, // and this may be an Array from another window. @@ -1480,11 +1497,12 @@ function Completion() //{{{ context.keys = { text: !full ? "leafName" : function (f) dir + f.leafName, description: function (f) f.isDirectory() ? "Directory" : "File", + isdir: function (f) f.isDirectory(), icon: function (f) f.isDirectory() ? "resource://gre/res/html/folder.png" : "moz-icon://" + f.leafName }; - context.compare = function ({ item: a }, { item: b }) - b.isDirectory() - a.isDirectory() || String.localeCompare(a.path, b.path); + context.compare = function (a, b) + b.isdir - a.isdir || String.localeCompare(a.text, b.text); if (options["wildignore"]) { @@ -1779,7 +1797,7 @@ function Completion() //{{{ if (tags) context.filters.push(function (item) tags. - every(function (tag) (context.getKey(item, "tags") || []). + every(function (tag) (item.tags || []). some(function (t) !compare(tag, t)))); context.anchored = false; @@ -1798,8 +1816,8 @@ function Completion() //{{{ // and all that don't match the tokens. let tokens = context.filter.split(/\s+/); context.filters.push(function (item) tokens.every( - function (tok) contains(context.getKey(item, "url"), tok) || - contains(context.getKey(item, "title"), tok))); + function (tok) contains(item.url, tok) || + contains(item.title, tok))); let re = RegExp(tokens.filter(util.identity).map(util.escapeRegex).join("|"), "g"); function highlight(item, text, i) process[i].call(this, item, template.highlightRegexp(text, re)); From e1d5236261a32c9fe34a43b63034ce72e8d7be93 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 13:54:35 -0500 Subject: [PATCH 08/18] Remove other uses of CompletionContextcompletion.jsgetKey --- common/content/completion.js | 2 +- common/content/template.js | 36 ++++++++++++++++-------------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/common/content/completion.js b/common/content/completion.js index be606b99..24a20e53 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -128,7 +128,7 @@ function CompletionContext(editor, name, offset) //{{{ * results. */ this.filters = [function (item) { - let text = Array.concat(this.getKey(item, "text")); + let text = Array.concat(item.text); for (let [i, str] in Iterator(text)) { if (this.match(String(str))) diff --git a/common/content/template.js b/common/content/template.js index 0f7a08a3..0baaaf00 100644 --- a/common/content/template.js +++ b/common/content/template.js @@ -49,8 +49,8 @@ const template = { } else { - var text = this.process[0].call(this, item, item.text || this.getKey(item, "text")); - var desc = this.process[1].call(this, item, this.getKey(item, "description")); + var text = this.process[0].call(this, item, item.text); + var desc = this.process[1].call(this, item, item.description); } // @@ -66,27 +66,23 @@ const template = { }, bookmarkDescription: function (item, text) - { - let extra = this.getKey(item, "extra"); - return <> - {text}  - { - !(extra && extra.length) ? "" : - - ({ - template.map(extra, function (e) - <>{e[0]}: {e[1]}, - <> /* Non-breaking space */) - }) - - } - - }, + <> + {text}  + { + !(item.extra && item.extra.length) ? "" : + + ({ + template.map(item.extra, function (e) + <>{e[0]}: {e[1]}, + <> /* Non-breaking space */) + }) + + } + , icon: function (item, text) { - let icon = this.getKey(item, "icon"); - return <>{icon ? : <>}{text} + return <>{item.icon ? : <>}{text} }, filter: function (str) {str}, From ef827139e4ce946b2fda88f3e28390f80ddbe5d7 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 14:36:11 -0500 Subject: [PATCH 09/18] Tie storage observers to a weak reference of window so they're automatically destroyed. --- common/content/options.js | 5 +---- common/modules/storage.jsm | 24 +++++++++++++++++++----- vimperator/content/bookmarks.js | 5 +---- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/common/content/options.js b/common/content/options.js index 0a244ab3..0a1008ff 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -320,10 +320,7 @@ function Options() //{{{ } storage.newMap("options", false); - storage.addObserver("options", optionObserver); - liberator.registerObserver("shutdown", function () { - storage.removeObserver("options", optionObserver); - }); + storage.addObserver("options", optionObserver, window); function storePreference(name, value) { diff --git a/common/modules/storage.jsm b/common/modules/storage.jsm index ffb96d2d..61ebf01e 100644 --- a/common/modules/storage.jsm +++ b/common/modules/storage.jsm @@ -253,27 +253,41 @@ var storage = { return this.newObject(key, ArrayStore, store, Array); }, - addObserver: function addObserver(key, callback) + addObserver: function addObserver(key, callback, ref) { + this.removeDeadObservers(); if (!(key in observers)) observers[key] = []; if (observers[key].indexOf(callback) == -1) - observers[key].push(callback); + observers[key].push({ ref: ref && Components.utils.getWeakReference(ref), callback: callback }); }, removeObserver: function (key, callback) { + this.removeDeadObservers(); if (!(key in observers)) return; - observers[key] = observers[key].filter(function (elem) elem != callback); + observers[key] = observers[key].filter(function (elem) elem.callback != callback); if (observers[key].length == 0) delete obsevers[key]; }, + removeDeadObservers: function () + { + for (let [key, ary] in Iterator(observers)) + { + observers[key] = ary = ary.filter(function (o) !o.ref || o.ref.get()); + if (!ary.length) + delete observers[key]; + } + }, + fireEvent: function fireEvent(key, event, arg) { - for each (callback in observers[key]) - callback(key, event, arg); + this.removeDeadObservers(); + // Safe, since we have our own Array object here. + for each (let observer in observers[key]) + observer.callback(key, event, arg); timers[key].tell(); }, diff --git a/vimperator/content/bookmarks.js b/vimperator/content/bookmarks.js index afb276e4..c21e2ee8 100644 --- a/vimperator/content/bookmarks.js +++ b/vimperator/content/bookmarks.js @@ -236,10 +236,7 @@ function Bookmarks() //{{{ }; var cache = storage.newObject("bookmark-cache", Cache, false); - storage.addObserver("bookmark-cache", bookmarkObserver); - liberator.registerObserver("shutdown", function () { - storage.removeObserver("bookmark-cache", bookmarkObserver); - }); + storage.addObserver("bookmark-cache", bookmarkObserver, window); liberator.registerObserver("enter", function () { if (options["preload"]) From 0583508b94de1018dfb6672d81bb5708d0b2c998 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 15:38:12 -0500 Subject: [PATCH 10/18] Fix onKeyPress error --- common/content/events.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/content/events.js b/common/content/events.js index c1432bbe..40128b8c 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -1300,7 +1300,7 @@ function Events() //{{{ let stop = true; // set to false if we should NOT consume this event but let Firefox handle it let win = document.commandDispatcher.focusedWindow; - if (win && win.document.designMode == "on" && !config.isComposeWindow) + if (win && win.document && win.document.designMode == "on" && !config.isComposeWindow) return false; // menus have their own command handlers From 1a13d07e9f467e9c4acddb8536800333a391c218 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 18:40:34 -0500 Subject: [PATCH 11/18] Unbreak :se! completion. --- common/content/completion.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/content/completion.js b/common/content/completion.js index fade644a..60dc0af6 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -1651,7 +1651,7 @@ function Completion() //{{{ context.anchored = false; context.title = ["Firefox Preference", "Value"]; context.keys = { text: function (item) item, description: function (item) options.getPref(item) }; - context.completions = service["prefs"].getChildList("", { value: 0 }); + context.completions = service["pref"].getChildList("", { value: 0 }); }, search: function search(context, noSuggest) From 2c325d40437a58d565907f4babbb3d802443da1b Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 18:54:49 -0500 Subject: [PATCH 12/18] Document some stuff in util.js --- common/content/util.js | 67 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/common/content/util.js b/common/content/util.js index 411c3dd2..475ff3c1 100644 --- a/common/content/util.js +++ b/common/content/util.js @@ -34,9 +34,21 @@ default xml namespace = XHTML; const util = { //{{{ + /** + * Array utility methods. + * @singleton + */ Array: { - // [["a", "b"], ["c", "d"]] -> { a: "b", c: "d" } - // From Common Lisp, more or less + /** + * Converts an array to an object. As in lisp, an assoc is an + * array of key-value pairs, which maps directly to an object, + * as such: + * [["a", "b"], ["c", "d"]] -> { a: "b", c: "d" } + * + * @param {Array[]} assoc + * @... {string} 0 - Key + * @... 1 - Value + */ assocToObj: function assocToObj(assoc) { let obj = {}; @@ -44,9 +56,18 @@ const util = { //{{{ return obj; }, - // flatten an array: [["foo", ["bar"]], ["baz"], "quux"] -> ["foo", ["bar"], "baz", "quux"] + /** + * Flatten an array, such that all elements of the array are + * joined into a single array: + * [["foo", ["bar"]], ["baz"], "quux"] -> ["foo", ["bar"], "baz", "quux"] + */ flatten: function flatten(ary) Array.concat.apply([], ary), + /** + * Returns an Iterator for an array's values. + * + * @returns {Iterator(Object)} + */ iterator: function iterator(ary) { let length = ary.length; @@ -54,6 +75,11 @@ const util = { //{{{ yield ary[i]; }, + /** + * Returns an Iterator for the arrays indices and values. + * + * @returns {Iterator([{number}, {Object}])} + */ iterator2: function (ary) { let length = ary.length; @@ -61,6 +87,14 @@ const util = { //{{{ yield [i, ary[i]]; }, + /** + * Filters out all duplicates from an array. If + * unsorted is false, the array is sorted before + * duplicates are removed. + * + * @param {Array} ary + * @param {boolean} unsorted + */ uniq: function uniq(ary, unsorted) { let ret = []; @@ -83,6 +117,11 @@ const util = { //{{{ } }, + /** + * Returns a shallow copy of obj. + * + * @param {Object} obj + */ cloneObject: function cloneObject(obj) { if (obj instanceof Array) @@ -93,13 +132,35 @@ const util = { //{{{ return newObj; }, + /** + * Clips a string to a given length. If the input string is longer + * than length, an elipsis is appended. + * + * @param {string} str + * @param {number} length + * @returns {string} + */ clip: function clip(str, length) { return str.length <= length ? str : str.substr(0, length - 3) + "..."; }, + /** + * Compares two strings, case insensitively. Return values are as + * in String#localeCompare. + * + * @param {string} a + * @param {string} b + * @returns {number} + */ compareIgnoreCase: function compareIgnoreCase(a, b) String.localeCompare(a.toLowerCase(), b.toLowerCase()), + /** + * Returns an object representing a Node's computed CSS style. + * + * @param {Node} node + * @returns {Object} + */ computedStyle: function computedStyle(node) { while (node instanceof Text && node.parentNode) From 2f0132cabcf5695e088dc665c6eba8ef147a6b2a Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 19:59:36 -0500 Subject: [PATCH 13/18] Sorry, minor feature that's more of a bug fix: Options/commands/mappings in :help now behave as links. --- common/content/help.js | 8 ++++++++ common/content/help.xul | 7 +++++++ vimperator/locale/en-US/asciidoc.conf | 11 ++++++----- vimperator/locale/en-US/browsing.txt | 2 +- vimperator/locale/en-US/help.js | 7 +++++++ vimperator/locale/en-US/xhtml11.css | 8 ++++++++ 6 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 common/content/help.js create mode 100644 common/content/help.xul create mode 100644 vimperator/locale/en-US/help.js diff --git a/common/content/help.js b/common/content/help.js new file mode 100644 index 00000000..b25ecf51 --- /dev/null +++ b/common/content/help.js @@ -0,0 +1,8 @@ + +const liberator = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] + .getService(Components.interfaces.nsIWindowWatcher) + .activeWindow + .liberator; + +liberator.help(decodeURIComponent(document.location.search.substr(1))); + diff --git a/common/content/help.xul b/common/content/help.xul new file mode 100644 index 00000000..16be6018 --- /dev/null +++ b/common/content/help.xul @@ -0,0 +1,7 @@ + + + + {doctitle} @@ -73,10 +74,10 @@ HEADER=
| key=
|
-option=| -option2='|' -command=| -mapping=| +option=| +option2='|' +command=| +mapping=| argument=| argument2={|} argument3=[|] diff --git a/vimperator/locale/en-US/browsing.txt b/vimperator/locale/en-US/browsing.txt index 97f43335..10ba2231 100644 --- a/vimperator/locale/en-US/browsing.txt +++ b/vimperator/locale/en-US/browsing.txt @@ -68,7 +68,7 @@ ________________________________________________________________________________ ||:tabopen[!] [arg1], [arg2], ...|| + ||t|| ________________________________________________________________________________ -Just like help::open[browsing.html#opening], but opens the resulting web page(s) +Just like [c]:open[c], but opens the resulting web page(s) in a new tab. When used with [!], the 'tabopen' value of the 'activate' option is negated. ________________________________________________________________________________ diff --git a/vimperator/locale/en-US/help.js b/vimperator/locale/en-US/help.js new file mode 100644 index 00000000..17a20a4e --- /dev/null +++ b/vimperator/locale/en-US/help.js @@ -0,0 +1,7 @@ + +document.addEventListener("click", function (event) { + let elem = event.target; + if (/^(option|mapping|command)$/.test(elem.className)) + elem.setAttribute("href", "chrome://liberator/content/help.xul?" + encodeURIComponent(elem.textContent.replace(/\s.*/, ""))); +}, true); + diff --git a/vimperator/locale/en-US/xhtml11.css b/vimperator/locale/en-US/xhtml11.css index 1ff321a5..194c0557 100644 --- a/vimperator/locale/en-US/xhtml11.css +++ b/vimperator/locale/en-US/xhtml11.css @@ -335,6 +335,14 @@ fieldset.paypal { font-weight: bold; color: #106326; } + +.option, .mapping, .command { + text-decoration: none; +} +.option:hover, .mapping:hover, .command:hover { + text-decoration: underline; +} + .quoteblock { margin-left: 140px; padding-bottom: 10px; From df7c7c9d51a15b0091e71f463319b1c26eb2b0a1 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 20 Dec 2008 23:48:56 -0500 Subject: [PATCH 14/18] Fix some generally silly, stupid, and/or annoying help quirks. --- common/content/help.js | 13 +++--- common/content/liberator.js | 61 ++++++++++++--------------- vimperator/locale/en-US/asciidoc.conf | 4 +- vimperator/locale/en-US/help.js | 22 +++++++++- 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/common/content/help.js b/common/content/help.js index b25ecf51..3ae6d96e 100644 --- a/common/content/help.js +++ b/common/content/help.js @@ -1,8 +1,11 @@ -const liberator = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] - .getService(Components.interfaces.nsIWindowWatcher) - .activeWindow - .liberator; +const win = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] + .getService(Components.interfaces.nsIWindowWatcher) + .activeWindow; +const liberator = win.liberator; -liberator.help(decodeURIComponent(document.location.search.substr(1))); +let page = liberator.findHelp(decodeURIComponent(document.location.search.substr(1))); +let url = "chrome://liberator/locale/" + page; + +win.getBrowser().loadURIWithFlags(url, Components.interfaces.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY, null, null, null); diff --git a/common/content/liberator.js b/common/content/liberator.js index eb9d6574..35a71efb 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -939,6 +939,28 @@ const liberator = (function () //{{{ return extensions.some(function (e) e.name == name); }, + findHelp: function (topic) + { + let items = completion.runCompleter("help", topic); + let partialMatch = null; + + function format(item) item[1] + "#" + encodeURIComponent(item[0]); + + for (let [i, item] in Iterator(items)) + { + if (item[0] == topic) + return format(item); + else if (partialMatch == -1 && item[0].indexOf(topic) > -1) + { + partialMatch = item; + } + } + + if (partialMatch) + return format(partialMatch); + return null; + }, + help: function (topic) { let where = (options["newtab"] && options.get("newtab").has("all", "help")) @@ -952,43 +974,16 @@ const liberator = (function () //{{{ liberator.open("chrome://liberator/locale/" + helpFile, where); else liberator.echomsg("Sorry, help file " + helpFile.quote() + " not found"); - return; } - function jumpToTag(file, tag) - { - liberator.open("chrome://liberator/locale/" + file, where); - // TODO: it would be better to wait for pageLoad - setTimeout(function () { - let elem = buffer.evaluateXPath('//*[@class="tag" and text()="' + tag + '"]').snapshotItem(0); - if (elem) - window.content.scrollTo(0, elem.getBoundingClientRect().top - 10); // 10px context - else - liberator.dump('no element: ' + '@class="tag" and text()="' + tag + '"\n' ); - }, 500); - } + let page = this.findHelp(topic); + if (page == null) + return liberator.echoerr("E149: Sorry, no help for " + topic); - let items = completion.runCompleter("help", topic); - let partialMatch = -1; - - for (let [i, item] in Iterator(items)) - { - if (item[0] == topic) - { - jumpToTag(item[1], item[0]); - return; - } - else if (partialMatch == -1 && item[0].indexOf(topic) > -1) - { - partialMatch = i; - } - } - - if (partialMatch > -1) - jumpToTag(items[partialMatch][1], items[partialMatch][0]); - else - liberator.echoerr("E149: Sorry, no help for " + topic); + liberator.open("chrome://liberator/locale/" + page, where); + if (where == this.CURRENT_TAB) + content.postMessage("fragmentChange", "*"); }, globalVariables: {}, diff --git a/vimperator/locale/en-US/asciidoc.conf b/vimperator/locale/en-US/asciidoc.conf index 41366f40..0a76bab0 100644 --- a/vimperator/locale/en-US/asciidoc.conf +++ b/vimperator/locale/en-US/asciidoc.conf @@ -76,8 +76,8 @@ tag=| key=
|
option=| option2='|' -command=| -mapping=| +command=| +mapping=| argument=| argument2={|} argument3=[|] diff --git a/vimperator/locale/en-US/help.js b/vimperator/locale/en-US/help.js index 17a20a4e..00889f12 100644 --- a/vimperator/locale/en-US/help.js +++ b/vimperator/locale/en-US/help.js @@ -1,7 +1,27 @@ +function checkFragment() +{ + let frag = document.location.hash.substr(1); + if (!frag || document.getElementById(frag)) + return; + let elem = document.evaluate('//*[@class="tag" and text()="' + frag + '"]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0); + if (elem) + window.content.scrollTo(0, elem.getBoundingClientRect().top - 10); // 10px context +} + +document.addEventListener("load", checkFragment, true); +window.addEventListener("message", function (event) { + if (event.data == "fragmentChange") + checkFragment(); +}, true); + document.addEventListener("click", function (event) { let elem = event.target; if (/^(option|mapping|command)$/.test(elem.className)) - elem.setAttribute("href", "chrome://liberator/content/help.xul?" + encodeURIComponent(elem.textContent.replace(/\s.*/, ""))); + var tag = elem.textContent.replace(/\s.*/, ""); + if (elem.className == "command") + tag = tag.replace(/\[.*?\]/g, ""); + if (tag) + elem.href = "chrome://liberator/content/help.xul?" + encodeURIComponent(tag); }, true); From fd8a656d1adaeaaf75e8e503060392e646e7e75d Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sun, 21 Dec 2008 00:02:33 -0500 Subject: [PATCH 15/18] Fix status bar for help pages when fragment identifier present. --- common/content/ui.js | 1 + 1 file changed, 1 insertion(+) diff --git a/common/content/ui.js b/common/content/ui.js index 0ad27fd6..d7fdc3b1 100644 --- a/common/content/ui.js +++ b/common/content/ui.js @@ -1800,6 +1800,7 @@ function StatusLine() //{{{ } else { + url = url.replace(RegExp("^chrome://liberator/locale/(\\S+\\.html)#(.*)"), function (m, n1, n2) n1 + " " + decodeURIComponent(n2) + " [Help]"); url = url.replace(RegExp("^chrome://liberator/locale/(\\S+\\.html)"), "$1 [Help]"); } From 8f49dd3b4b28cbf53000f0ee58e269a14d2fb514 Mon Sep 17 00:00:00 2001 From: anekos Date: Sun, 21 Dec 2008 15:03:28 +0900 Subject: [PATCH 16/18] Fix argument name. Thanks tsukkee. --- vimperator/content/bookmarks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vimperator/content/bookmarks.js b/vimperator/content/bookmarks.js index 12bf8276..2335eebc 100644 --- a/vimperator/content/bookmarks.js +++ b/vimperator/content/bookmarks.js @@ -559,12 +559,12 @@ function Bookmarks() //{{{ return searchEngines; }, - getSuggestions: function getSuggestions(engine, query, callback) + getSuggestions: function getSuggestions(engineName, query, callback) { let ss = service.browserSearch; const responseType = "application/x-suggestions+json"; - let engine = ss.getEngineByAlias(engine); + let engine = ss.getEngineByAlias(engineName); if (engine && engine.supportsResponseType(responseType)) var queryURI = engine.getSubmission(query, responseType).uri.spec; if (!queryURI) From 9ac029441f7179d0bd260a6bf08c067584ede121 Mon Sep 17 00:00:00 2001 From: anekos Date: Sun, 21 Dec 2008 15:40:12 +0900 Subject: [PATCH 17/18] Fix typo. --- common/content/options.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/content/options.js b/common/content/options.js index dfccebed..c20882db 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -334,7 +334,7 @@ function Options() //{{{ switch (typeof value) { case "string": - if (type == service["pref"].PREF_INVALID || type == service["prefBranch"].PREF_STRING) + if (type == service["pref"].PREF_INVALID || type == service["pref"].PREF_STRING) service["pref"].setCharPref(name, value); else if (type == service["pref"].PREF_INT) liberator.echoerr("E521: Number required after =: " + name + "=" + value); From fbb1f33faba482cff7976ddb80fb3f8f1cdaa161 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sun, 21 Dec 2008 22:01:13 +1100 Subject: [PATCH 18/18] Use the RegExp global function rather than calling the constructor. --- common/content/commands.js | 2 +- common/content/events.js | 4 ++-- common/content/util.js | 2 +- vimperator/content/bookmarks.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/content/commands.js b/common/content/commands.js index 6e7bd58e..d2682d54 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -176,7 +176,7 @@ Command.prototype = { let matches = args.match(/(.*)<<\s*(\S+)$/); if (matches && matches[2]) { - commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"), + commandline.inputMultiline(RegExp("^" + matches[2] + "$", "m"), function (args) { exec(matches[1] + "\n" + args); }); return; } diff --git a/common/content/events.js b/common/content/events.js index ef0d429c..7c7d486d 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -817,13 +817,13 @@ function Events() //{{{ if (!filter) return macros; - let re = new RegExp(filter); + let re = RegExp(filter); return ([macro, keys] for ([macro, keys] in macros) if (re.test(macro))); }, deleteMacros: function (filter) { - let re = new RegExp(filter); + let re = RegExp(filter); for (let [item,] in macros) { diff --git a/common/content/util.js b/common/content/util.js index 475ff3c1..41b9d3f3 100644 --- a/common/content/util.js +++ b/common/content/util.js @@ -475,7 +475,7 @@ const util = { //{{{ // and returns an array ['www.google.com/search?q=bla', 'www.osnews.com'] stringToURLArray: function stringToURLArray(str) { - let urls = str.split(new RegExp("\s*" + options["urlseparator"] + "\s*")); + let urls = str.split(RegExp("\s*" + options["urlseparator"] + "\s*")); return urls.map(function (url) { try diff --git a/vimperator/content/bookmarks.js b/vimperator/content/bookmarks.js index 2335eebc..277b5ccd 100644 --- a/vimperator/content/bookmarks.js +++ b/vimperator/content/bookmarks.js @@ -1003,7 +1003,7 @@ function QuickMarks() //{{{ remove: function remove(filter) { - var pattern = new RegExp("[" + filter.replace(/\s+/g, "") + "]"); + var pattern = RegExp("[" + filter.replace(/\s+/g, "") + "]"); for (let [qmark,] in qmarks) {