diff --git a/NEWS b/NEWS index 718c0582..15e9f5f0 100644 --- a/NEWS +++ b/NEWS @@ -53,7 +53,7 @@ * added a visual bell and replaced 'beep' with 'visualbell' * added vimperator logo (can be seen in the addons manager) * added 'hlsearch','incsearch', 'ignorecase' and 'smartcase' options - * many small bug fixes and enhancments + * many small bug fixes and enhancements 2007-09-03: * version 0.5.1 diff --git a/content/bookmarks.js b/content/bookmarks.js index 9d473305..a25e36e8 100644 --- a/content/bookmarks.js +++ b/content/bookmarks.js @@ -33,21 +33,21 @@ vimperator.Bookmarks = function () //{{{ ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - const search_service = Components.classes["@mozilla.org/browser/search-service;1"]. + const searchService = Components.classes["@mozilla.org/browser/search-service;1"]. getService(Components.interfaces.nsIBrowserSearchService); - const rdf_service = Components.classes["@mozilla.org/rdf/rdf-service;1"]. - getService( Components.interfaces.nsIRDFService ); + const rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"]. + getService(Components.interfaces.nsIRDFService); var bookmarks = null; var keywords = null; if (vimperator.options["preload"]) - setTimeout(function () { load(); } , 100); + setTimeout(function () { load(); }, 100); function load() { // update our bookmark cache - var root = rdf_service.GetResource("NC:BookmarksRoot"); + var root = rdfService.GetResource("NC:BookmarksRoot"); bookmarks = []; // also clear our bookmark cache keywords = []; @@ -56,15 +56,15 @@ vimperator.Bookmarks = function () //{{{ // getAllChildren(root) ignores the BTF // NOTE: there's probably a better way to do this... - var btf_bmarks = []; - BookmarksUtils.getAllChildren(BMSVC.getBookmarksToolbarFolder(), btf_bmarks); + var btfBmarks = []; + BookmarksUtils.getAllChildren(BMSVC.getBookmarksToolbarFolder(), btfBmarks); - bmarks = bmarks.concat(btf_bmarks); + bmarks = bmarks.concat(btfBmarks); for (var i = 0; i < bmarks.length; i++) { if (bmarks[i][0] && bmarks[i][1]) - bookmarks.push([bmarks[i][1].Value, bmarks[i][0].Value ]); + bookmarks.push([bmarks[i][1].Value, bmarks[i][0].Value]); // keyword if (bmarks[i][1] && bmarks[i][2]) @@ -76,285 +76,290 @@ vimperator.Bookmarks = function () //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - // FIXME: add filtering here rather than having to calling - // get_bookmark_completions() - this.get = function () - { - if (!bookmarks) - load(); + return { - return bookmarks; - } - - // TODO: keyword support - this.add = function (title, uri, keyword) - { - if (!bookmarks) - load(); - - folder = rdf_service.GetResource("NC:BookmarksRoot"); - var rSource = BookmarksUtils.createBookmark(title, uri, keyword, title); - var selection = BookmarksUtils.getSelectionFromResource(rSource); - var target = BookmarksUtils.getTargetFromFolder(folder); - BookmarksUtils.insertAndCheckSelection("newbookmark", selection, target); - - //also update bookmark cache - bookmarks.unshift([uri, title]); - return true; - } - - // NOTE: no idea what it does, it Just Works (TM) - // returns number of deleted bookmarks - this.remove = function (url) - { - var deleted = 0; - if (!url) - return 0; - - // gNC_NS for trunk, NC_NS for 1.X - //try { var pNC_NS; pNC_NS = gNC_NS;} catch (err) { pNC_NS = NC_NS;} - if (!BMSVC || !BMDS || !RDF || !gNC_NS) // defined from firefox - return 0; - - var curfolder = RDF.GetResource("NC:BookmarksRoot"); - var urlArc = RDF.GetResource(gNC_NS + "URL"); - var urlLiteral = RDF.GetLiteral(url); - if (BMDS.hasArcIn(urlLiteral, urlArc)) + // FIXME: add filtering here rather than having to calling + // v.completion.bookmark() + get: function () { - var bmResources, bmResource, title, uri, type, ptype; - bmResources = BMSVC.GetSources(urlArc, urlLiteral, true); - while (bmResources.hasMoreElements()) - { - bmResource = bmResources.getNext(); - type = BookmarksUtils.resolveType(bmResource); - if (type != "ImmutableBookmark") - { - ptype = BookmarksUtils.resolveType(BMSVC.getParent(bmResource)); - // alert(type); - // if ( type == "Folder") // store the current folder - // curfolder = bmResource; - if ( (type == "Bookmark" || type == "IEFavorite") && ptype != "Livemark") - { - title = BookmarksUtils.getProperty(bmResource, gNC_NS + "Name"); - uri = BookmarksUtils.getProperty(bmResource, gNC_NS + "URL"); + if (!bookmarks) + load(); - if (uri == url) + return bookmarks; + }, + + // TODO: keyword support + add: function (title, uri, keyword) + { + if (!bookmarks) + load(); + + folder = rdfService.GetResource("NC:BookmarksRoot"); + var rSource = BookmarksUtils.createBookmark(title, uri, keyword, title); + var selection = BookmarksUtils.getSelectionFromResource(rSource); + var target = BookmarksUtils.getTargetFromFolder(folder); + BookmarksUtils.insertAndCheckSelection("newbookmark", selection, target); + + //also update bookmark cache + bookmarks.unshift([uri, title]); + return true; + }, + + // NOTE: no idea what it does, it Just Works (TM) + // returns number of deleted bookmarks + remove: function (url) + { + var deleted = 0; + if (!url) + return 0; + + // gNC_NS for trunk, NC_NS for 1.X + //try { var pNC_NS; pNC_NS = gNC_NS;} catch (err) { pNC_NS = NC_NS;} + if (!BMSVC || !BMDS || !RDF || !gNC_NS) // defined from firefox + return 0; + + var curfolder = RDF.GetResource("NC:BookmarksRoot"); + var urlArc = RDF.GetResource(gNC_NS + "URL"); + var urlLiteral = RDF.GetLiteral(url); + if (BMDS.hasArcIn(urlLiteral, urlArc)) + { + var bmResources, bmResource, title, uri, type, ptype; + bmResources = BMSVC.GetSources(urlArc, urlLiteral, true); + while (bmResources.hasMoreElements()) + { + bmResource = bmResources.getNext(); + type = BookmarksUtils.resolveType(bmResource); + if (type != "ImmutableBookmark") + { + ptype = BookmarksUtils.resolveType(BMSVC.getParent(bmResource)); + // alert(type); + // if (type == "Folder") // store the current folder + // curfolder = bmResource; + if ((type == "Bookmark" || type == "IEFavorite") && ptype != "Livemark") { - RDFC.Init(BMDS, BMSVC.getParent(bmResource)); - RDFC.RemoveElement(bmResource, true); - deleted++; + title = BookmarksUtils.getProperty(bmResource, gNC_NS + "Name"); + uri = BookmarksUtils.getProperty(bmResource, gNC_NS + "URL"); + + if (uri == url) + { + RDFC.Init(BMDS, BMSVC.getParent(bmResource)); + RDFC.RemoveElement(bmResource, true); + deleted++; + } } } } } - } - // also update bookmark cache, if we removed at least one bookmark - if (deleted > 0) - load(); + // also update bookmark cache, if we removed at least one bookmark + if (deleted > 0) + load(); - return deleted; - } + return deleted; + }, - // also ensures that each search engine has a Vimperator-friendly alias - this.getSearchEngines = function () - { - var search_engines = []; - var firefox_engines = search_service.getVisibleEngines({ }); - for (var i in firefox_engines) + // also ensures that each search engine has a Vimperator-friendly alias + getSearchEngines: function () { - var alias = firefox_engines[i].alias; - if (!alias || !alias.match(/^[a-z0-9_-]+$/)) - alias = firefox_engines[i].name.replace(/^\W*([a-zA-Z_-]+).*/, "$1").toLowerCase(); - if (!alias) - alias = "search"; // for search engines which we can't find a suitable alias - - // make sure we can use search engines which would have the same alias (add numbers at the end) - var newalias = alias; - for (var j = 1; j <= 10; j++) // <=10 is intentional + var searchEngines = []; + var firefoxEngines = searchService.getVisibleEngines({ }); + for (var i in firefoxEngines) { - if (!search_engines.some(function (item) { return (item[0] == newalias); })) - break; + var alias = firefoxEngines[i].alias; + if (!alias || !alias.match(/^[a-z0-9_-]+$/)) + alias = firefoxEngines[i].name.replace(/^\W*([a-zA-Z_-]+).*/, "$1").toLowerCase(); + if (!alias) + alias = "search"; // for search engines which we can't find a suitable alias - newalias = alias + j; + // make sure we can use search engines which would have the same alias (add numbers at the end) + var newAlias = alias; + for (var j = 1; j <= 10; j++) // <=10 is intentional + { + if (!searchEngines.some(function (item) { return (item[0] == newAlias); })) + break; + + newAlias = alias + j; + } + // only write when it changed, writes are really slow + if (firefoxEngines[i].alias != newAlias) + firefoxEngines[i].alias = newAlias; + + searchEngines.push([firefoxEngines[i].alias, firefoxEngines[i].description]); } - // only write when it changed, writes are really slow - if (firefox_engines[i].alias != newalias) - firefox_engines[i].alias = newalias; - search_engines.push([firefox_engines[i].alias, firefox_engines[i].description]); - } + return searchEngines; + }, - return search_engines; - } - - // format of returned array: - // [keyword, helptext, url] - this.getKeywords = function () - { - if (!keywords) - load(); - - return keywords; - } - - // if @param engine_name is null, it uses the default search engine - // @returns the url for the search string - // if the search also requires a postdata, [url, postdata] is returned - this.getSearchURL = function (text, engine_name) - { - var url = null; - var postdata = null; - if (!engine_name) - engine_name = vimperator.options["defsearch"]; - - // we need to make sure our custom alias have been set, even if the user - // did not :open once before - this.getSearchEngines(); - - // first checks the search engines for a match - var engine = search_service.getEngineByAlias(engine_name); - if (engine) - { - if (text) - { - var submission = engine.getSubmission(text, null); - url = submission.uri.spec; - postdata = submission.postData; - } - else - url = engine.searchForm; - } - else // check for keyword urls + // TODO: add filtering + // format of returned array: + // [keyword, helptext, url] + getKeywords: function () { if (!keywords) load(); - for (var i in keywords) + return keywords; + }, + + // if @param engineName is null, it uses the default search engine + // @returns the url for the search string + // if the search also requires a postData, [url, postData] is returned + getSearchURL: function (text, engineName) + { + var url = null; + var postData = null; + if (!engineName) + engineName = vimperator.options["defsearch"]; + + // we need to make sure our custom alias have been set, even if the user + // did not :open once before + this.getSearchEngines(); + + // first checks the search engines for a match + var engine = searchService.getEngineByAlias(engineName); + if (engine) { - if (keywords[i][0] == engine_name) + if (text) { - if (text == null) - text = ""; - url = keywords[i][2].replace(/%s/g, encodeURIComponent(text)); - break; + var submission = engine.getSubmission(text, null); + url = submission.uri.spec; + postData = submission.postData; } - } - } - - // if we came here, the engine_name is neither a search engine or URL - if (postdata) - return [url, postdata]; - else - return url; // can be null - } - - this.list = function (filter, fullmode) - { - if (fullmode) - { - vimperator.open("chrome://browser/content/bookmarks/bookmarksPanel.xul", vimperator.NEW_TAB); - } - else - { - var items = vimperator.completion.get_bookmark_completions(filter); - - if (items.length == 0) - { - if (filter.length > 0) - vimperator.echoerr("E283: No bookmarks matching \"" + filter + "\""); else - vimperator.echoerr("No bookmarks set"); - - return; + url = engine.searchForm; } - - var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + - ""; - for (var i = 0; i < items.length; i++) + else // check for keyword urls { - var title = vimperator.util.escapeHTML(items[i][1]); - if (title.length > 50) - title = title.substr(0, 47) + "..."; - var url = vimperator.util.escapeHTML(items[i][0]); - list += ""; - } - list += "
titleURL
" + title + "" + url + "
"; + if (!keywords) + load(); - vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); - } - } - - // res = parseBookmarkString("-t tag1,tag2 -T title http://www.orf.at"); - // res.tags is an array of tags - // res.title is the title or "" if no one was given - // res.url is the url as a string - // returns null, if parsing failed - this.parseBookmarkString = function (str) - { - var res = {}; - res.tags = []; - res.title = null; - res.url = null; - - var re_title = /^\s*((-t|--title)\s+(\w+|\".*\"))(.*)/; - var re_tags = /^\s*((-T|--tags)\s+((\w+)(,\w+)*))(.*)/; - var re_url = /^\s*(\".+\"|\S+)(.*)/; - - var match_tags = null; - var match_title = null; - var match_url = null; - - while (!str.match(/^\s*$/)) - { - // first check for --tags - match_tags = str.match(re_tags); - if (match_tags != null) - { - str = match_tags[match_tags.length - 1]; // the last captured parenthesis is the rest of the string - tags = match_tags[3].split(","); - res.tags = res.tags.concat(tags); - } - else // then for --titles - { - - match_title = str.match(re_title); - if (match_title != null) + for (var i in keywords) { - // only one title allowed - if (res.title != null) - return null; - - str = match_title[match_title.length - 1]; // the last captured parenthesis is the rest of the string - var title = match_title[3]; - if (title.charAt(0) == '"') - title = title.substring(1, title.length - 1); - res.title = title; - } - else // at last check for a URL - { - match_url = str.match(re_url); - if (match_url != null) + if (keywords[i][0] == engineName) { - // only one url allowed - if (res.url != null) + if (text == null) + text = ""; + url = keywords[i][2].replace(/%s/g, encodeURIComponent(text)); + break; + } + } + } + + // if we came here, the engineName is neither a search engine or URL + if (postData) + return [url, postData]; + else + return url; // can be null + }, + + list: function (filter, fullmode) + { + if (fullmode) + { + vimperator.open("chrome://browser/content/bookmarks/bookmarksPanel.xul", vimperator.NEW_TAB); + } + else + { + var items = vimperator.completion.bookmark(filter); + + if (items.length == 0) + { + if (filter.length > 0) + vimperator.echoerr("E283: No bookmarks matching \"" + filter + "\""); + else + vimperator.echoerr("No bookmarks set"); + + return; + } + + var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + + ""; + for (var i = 0; i < items.length; i++) + { + var title = vimperator.util.escapeHTML(items[i][1]); + if (title.length > 50) + title = title.substr(0, 47) + "..."; + var url = vimperator.util.escapeHTML(items[i][0]); + list += ""; + } + list += "
titleURL
" + title + "" + url + "
"; + + vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); + } + }, + + // res = parseBookmarkString("-t tag1,tag2 -T title http://www.orf.at"); + // res.tags is an array of tags + // res.title is the title or "" if no one was given + // res.url is the url as a string + // returns null, if parsing failed + parseBookmarkString: function (str) + { + var res = {}; + res.tags = []; + res.title = null; + res.url = null; + + var reTitle = /^\s*((-t|--title)\s+(\w+|\".*\"))(.*)/; + var reTags = /^\s*((-T|--tags)\s+((\w+)(,\w+)*))(.*)/; + var reUrl = /^\s*(\".+\"|\S+)(.*)/; + + var matchTags = null; + var matchTitle = null; + var matchUrl = null; + + while (!str.match(/^\s*$/)) + { + // first check for --tags + matchTags = str.match(reTags); + if (matchTags != null) + { + str = matchTags[matchTags.length - 1]; // the last captured parenthesis is the rest of the string + tags = matchTags[3].split(","); + res.tags = res.tags.concat(tags); + } + else // then for --titles + { + + matchTitle = str.match(reTitle); + if (matchTitle != null) + { + // only one title allowed + if (res.title != null) return null; - str = match_url[match_url.length - 1]; // the last captured parenthesis is the rest of the string - url = match_url[1]; - if (url.charAt(0) == '"') - url = url.substring(1, url.length - 1); - res.url = url; + str = matchTitle[matchTitle.length - 1]; // the last captured parenthesis is the rest of the string + var title = matchTitle[3]; + if (title.charAt(0) == '"') + title = title.substring(1, title.length - 1); + res.title = title; + } + else // at last check for a URL + { + matchUrl = str.match(reUrl); + if (matchUrl != null) + { + // only one url allowed + if (res.url != null) + return null; + + str = matchUrl[matchUrl.length - 1]; // the last captured parenthesis is the rest of the string + url = matchUrl[1]; + if (url.charAt(0) == '"') + url = url.substring(1, url.length - 1); + res.url = url; + } + else + return null; // no url, tag or title found but still text left, abort } - else - return null; // no url, tag or title found but still text left, abort } } + return res; } - return res; - } + + }; //}}} -} //}}} +}; //}}} vimperator.History = function () //{{{ { @@ -362,15 +367,15 @@ vimperator.History = function () //{{{ ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - const rdf_service = Components.classes["@mozilla.org/rdf/rdf-service;1"]. - getService( Components.interfaces.nsIRDFService ); - const global_history_service = Components.classes["@mozilla.org/browser/global-history;2"]. + const rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"]. + getService(Components.interfaces.nsIRDFService); + const globalHistoryService = Components.classes["@mozilla.org/browser/global-history;2"]. getService(Components.interfaces.nsIRDFDataSource); var history = null; if (vimperator.options["preload"]) - setTimeout(function () { load(); } , 100); + setTimeout(function () { load(); }, 100); function load() { @@ -383,13 +388,13 @@ vimperator.History = function () //{{{ if (historytree.hidden) { historytree.hidden = false; - historytree.database.AddDataSource(global_history_service); + historytree.database.AddDataSource(globalHistoryService); } if (!historytree.ref) historytree.ref = "NC:HistoryRoot"; - var nameResource = rdf_service.GetResource(gNC_NS + "Name"); + var nameResource = rdfService.GetResource(gNC_NS + "Name"); var builder = historytree.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder); var count = historytree.view.rowCount; @@ -416,108 +421,112 @@ vimperator.History = function () //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - // FIXME: add filtering here rather than having to call - // get_bookmark_completions() - this.get = function () - { - if (!history) - load(); + return { - return history; - } - - this.add = function (url, title) - { - if (!history) - load(); - - history = history.filter(function (elem) { - return elem[0] != url; - }); - - history.unshift([url, title]); - return true; - }; - - // TODO: better names? - // and move to vimperator.buffer.? - this.stepTo = function (steps) - { - var index = getWebNavigation().sessionHistory.index + steps; - - if (index >= 0 && index < getWebNavigation().sessionHistory.count) + // FIXME: add filtering here rather than having to call + // v.completion.history() + get: function () { - getWebNavigation().gotoIndex(index); - } - else + if (!history) + load(); + + return history; + }, + + add: function (url, title) { - vimperator.beep(); - } - } + if (!history) + load(); - this.goToStart = function () - { - var index = getWebNavigation().sessionHistory.index; + history = history.filter(function (elem) { + return elem[0] != url; + }); - if (index == 0) + history.unshift([url, title]); + return true; + }, + + // TODO: better names? + // and move to vimperator.buffer.? + stepTo: function (steps) { - vimperator.beep(); - return; - } + var index = getWebNavigation().sessionHistory.index + steps; - getWebNavigation().gotoIndex(0); - } - - this.goToEnd = function () - { - var index = getWebNavigation().sessionHistory.index; - var max = getWebNavigation().sessionHistory.count - 1; - - if (index == max) - { - vimperator.beep(); - return; - } - - getWebNavigation().gotoIndex(max); - } - - this.list = function (filter, fullmode) - { - if (fullmode) - { - vimperator.open("chrome://browser/content/history/history-panel.xul", vimperator.NEW_TAB); - } - else - { - var items = vimperator.completion.get_history_completions(filter); - - if (items.length == 0) + if (index >= 0 && index < getWebNavigation().sessionHistory.count) { - if (filter.length > 0) - vimperator.echoerr("E283: No history matching \"" + filter + "\""); - else - vimperator.echoerr("No history set"); + getWebNavigation().gotoIndex(index); + } + else + { + vimperator.beep(); + } + }, + goToStart: function () + { + var index = getWebNavigation().sessionHistory.index; + + if (index == 0) + { + vimperator.beep(); return; } - var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + - ""; - for (var i = 0; i < items.length; i++) + getWebNavigation().gotoIndex(0); + }, + + goToEnd: function () + { + var index = getWebNavigation().sessionHistory.index; + var max = getWebNavigation().sessionHistory.count - 1; + + if (index == max) { - var title = vimperator.util.escapeHTML(items[i][1]); - if (title.length > 50) - title = title.substr(0, 47) + "..."; - var url = vimperator.util.escapeHTML(items[i][0]); - list += ""; + vimperator.beep(); + return; + } + + getWebNavigation().gotoIndex(max); + }, + + list: function (filter, fullmode) + { + if (fullmode) + { + vimperator.open("chrome://browser/content/history/history-panel.xul", vimperator.NEW_TAB); + } + else + { + var items = vimperator.completion.history(filter); + + if (items.length == 0) + { + if (filter.length > 0) + vimperator.echoerr("E283: No history matching \"" + filter + "\""); + else + vimperator.echoerr("No history set"); + + return; + } + + var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + + "
titleURL
" + title + "" + url + "
"; + for (var i = 0; i < items.length; i++) + { + var title = vimperator.util.escapeHTML(items[i][1]); + if (title.length > 50) + title = title.substr(0, 47) + "..."; + var url = vimperator.util.escapeHTML(items[i][0]); + list += ""; + } + list += "
titleURL
" + title + "" + url + "
"; + vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); } - list += ""; - vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); } - } + + }; //}}} -} //}}} +}; //}}} vimperator.Marks = function () //{{{ { @@ -525,24 +534,24 @@ vimperator.Marks = function () //{{{ ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - var local_marks = {}; - var url_marks = {}; - var pending_jumps = []; - var appcontent = document.getElementById("appcontent"); + var localMarks = {}; + var urlMarks = {}; + var pendingJumps = []; + var appContent = document.getElementById("appcontent"); - if (appcontent) - appcontent.addEventListener("load", onPageLoad, true); + if (appContent) + appContent.addEventListener("load", onPageLoad, true); function onPageLoad(event) { var win = event.originalTarget.defaultView; - for (var i = 0, length = pending_jumps.length; i < length; i++) + for (var i = 0, length = pendingJumps.length; i < length; i++) { - var mark = pending_jumps[i]; + var mark = pendingJumps[i]; if (win.location.href == mark.location) { win.scrollTo(mark.position.x * win.scrollMaxX, mark.position.y * win.scrollMaxY); - pending_jumps.splice(i, 1); + pendingJumps.splice(i, 1); return; } } @@ -550,17 +559,17 @@ vimperator.Marks = function () //{{{ function removeLocalMark(mark) { - if (mark in local_marks) + if (mark in localMarks) { var win = window.content; - for (var i = 0; i < local_marks[mark].length; i++) + for (var i = 0; i < localMarks[mark].length; i++) { - if (local_marks[mark][i].location == win.location.href) + if (localMarks[mark][i].location == win.location.href) { - vimperator.log("Deleting local mark: " + mark + " | " + local_marks[mark][i].location + " | (" + local_marks[mark][i].position.x + ", " + local_marks[mark][i].position.y + ") | tab: " + vimperator.tabs.index(local_marks[mark][i].tab), 5); - local_marks[mark].splice(i, 1); - if (local_marks[mark].length == 0) - delete local_marks[mark]; + vimperator.log("Deleting local mark: " + mark + " | " + localMarks[mark][i].location + " | (" + localMarks[mark][i].position.x + ", " + localMarks[mark][i].position.y + ") | tab: " + vimperator.tabs.index(localMarks[mark][i].tab), 5); + localMarks[mark].splice(i, 1); + if (localMarks[mark].length == 0) + delete localMarks[mark]; break; } } @@ -569,10 +578,10 @@ vimperator.Marks = function () //{{{ function removeURLMark(mark) { - if (mark in url_marks) + if (mark in urlMarks) { - vimperator.log("Deleting URL mark: " + mark + " | " + url_marks[mark].location + " | (" + url_marks[mark].position.x + ", " + url_marks[mark].position.y + ") | tab: " + vimperator.tabs.index(url_marks[mark].tab), 5); - delete url_marks[mark]; + vimperator.log("Deleting URL mark: " + mark + " | " + urlMarks[mark].location + " | (" + urlMarks[mark].position.x + ", " + urlMarks[mark].position.y + ") | tab: " + vimperator.tabs.index(urlMarks[mark].tab), 5); + delete urlMarks[mark]; } } @@ -591,12 +600,12 @@ vimperator.Marks = function () //{{{ // local marks var lmarks = []; - for (var mark in local_marks) + for (var mark in localMarks) { - for (var i = 0; i < local_marks[mark].length; i++) + for (var i = 0; i < localMarks[mark].length; i++) { - if (local_marks[mark][i].location == window.content.location.href) - lmarks.push([mark, local_marks[mark][i]]); + if (localMarks[mark][i].location == window.content.location.href) + lmarks.push([mark, localMarks[mark][i]]); } } lmarks.sort(); @@ -604,8 +613,8 @@ vimperator.Marks = function () //{{{ // URL marks var umarks = []; - for (var mark in url_marks) - umarks.push([mark, url_marks[mark]]); + for (var mark in urlMarks) + umarks.push([mark, urlMarks[mark]]); // FIXME: why does umarks.sort() cause a "Component is not available = // NS_ERROR_NOT_AVAILABLE" exception when used here? umarks.sort(function (a, b) { @@ -624,155 +633,159 @@ vimperator.Marks = function () //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - // TODO: add support for frameset pages - this.add = function (mark) - { - var win = window.content; + return { - if (win.document.body.localName.toLowerCase() == "frameset") - { - vimperator.echoerr("marks support for frameset pages not implemented yet"); - return; - } - - var x = win.scrollMaxX ? win.pageXOffset / win.scrollMaxX : 0; - var y = win.scrollMaxY ? win.pageYOffset / win.scrollMaxY : 0; - var position = { x: x, y: y }; - - if (isURLMark(mark)) - { - vimperator.log("Adding URL mark: " + mark + " | " + win.location.href + " | (" + position.x + ", " + position.y + ") | tab: " + vimperator.tabs.index(vimperator.tabs.getTab()), 5); - url_marks[mark] = { location: win.location.href, position: position, tab: vimperator.tabs.getTab() }; - } - else if (isLocalMark(mark)) - { - // remove any previous mark of the same name for this location - removeLocalMark(mark); - if (!local_marks[mark]) - local_marks[mark] = []; - vimperator.log("Adding local mark: " + mark + " | " + win.location.href + " | (" + position.x + ", " + position.y + ")", 5); - local_marks[mark].push({ location: win.location.href, position: position }); - } - } - - this.remove = function (filter, special) - { - if (special) - { - // :delmarks! only deletes a-z marks - for (var mark in local_marks) - removeLocalMark(mark); - } - else - { - var pattern = new RegExp("[" + filter.replace(/\s+/g, "") + "]"); - for (var mark in url_marks) - { - if (pattern.test(mark)) - removeURLMark(mark); - } - for (var mark in local_marks) - { - if (pattern.test(mark)) - removeLocalMark(mark); - } - } - } - - this.jumpTo = function (mark) - { - var ok = false; - - if (isURLMark(mark)) - { - var slice = url_marks[mark]; - if (slice && slice.tab && slice.tab.linkedBrowser) - { - if (!slice.tab.parentNode) - { - pending_jumps.push(slice); - // NOTE: this obviously won't work on generated pages using - // non-unique URLs, like Vimperator's help :( - vimperator.open(slice.location, vimperator.NEW_TAB); - return; - } - var index = vimperator.tabs.index(slice.tab); - if (index != -1) - { - vimperator.tabs.select(index); - var win = slice.tab.linkedBrowser.contentWindow; - if (win.location.href != slice.location) - { - pending_jumps.push(slice); - win.location.href = slice.location; - return; - } - vimperator.log("Jumping to URL mark: " + mark + " | " + slice.location + " | (" + slice.position.x + ", " + slice.position.y + ") | tab: " + vimperator.tabs.index(slice.tab), 5); - win.scrollTo(slice.position.x * win.scrollMaxX, slice.position.y * win.scrollMaxY); - ok = true; - } - } - } - else if (isLocalMark(mark)) + // TODO: add support for frameset pages + add: function (mark) { var win = window.content; - var slice = local_marks[mark] || []; - for (var i = 0; i < slice.length; i++) + if (win.document.body.localName.toLowerCase() == "frameset") { - if (win.location.href == slice[i].location) - { - vimperator.log("Jumping to local mark: " + mark + " | " + slice[i].location + " | (" + slice[i].position.x + ", " + slice[i].position.y + ")", 5); - win.scrollTo(slice[i].position.x * win.scrollMaxX, slice[i].position.y * win.scrollMaxY); - ok = true; - } - } - } - - if (!ok) - vimperator.echoerr("E20: Mark not set"); // FIXME: move up? - } - - this.list = function (filter) - { - var marks = getSortedMarks(); - - if (marks.length == 0) - { - vimperator.echoerr("No marks set"); - return; - } - - if (filter.length > 0) - { - marks = marks.filter(function (mark) { - if (filter.indexOf(mark[0]) > -1) - return mark; - }); - if (marks.length == 0) - { - vimperator.echoerr("E283: No marks matching \"" + filter + "\""); + vimperator.echoerr("marks support for frameset pages not implemented yet"); return; } - } - var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + - ""; - for (var i = 0; i < marks.length; i++) + var x = win.scrollMaxX ? win.pageXOffset / win.scrollMaxX : 0; + var y = win.scrollMaxY ? win.pageYOffset / win.scrollMaxY : 0; + var position = { x: x, y: y }; + + if (isURLMark(mark)) + { + vimperator.log("Adding URL mark: " + mark + " | " + win.location.href + " | (" + position.x + ", " + position.y + ") | tab: " + vimperator.tabs.index(vimperator.tabs.getTab()), 5); + urlMarks[mark] = { location: win.location.href, position: position, tab: vimperator.tabs.getTab() }; + } + else if (isLocalMark(mark)) + { + // remove any previous mark of the same name for this location + removeLocalMark(mark); + if (!localMarks[mark]) + localMarks[mark] = []; + vimperator.log("Adding local mark: " + mark + " | " + win.location.href + " | (" + position.x + ", " + position.y + ")", 5); + localMarks[mark].push({ location: win.location.href, position: position }); + } + }, + + remove: function (filter, special) { - list += "" + - "" + - "" + - "" + - "" + - ""; - } - list += "
marklinecolfile
" + marks[i][0] + "" + Math.round(marks[i][1].position.y * 100) + "%" + Math.round(marks[i][1].position.x * 100) + "%" + vimperator.util.escapeHTML(marks[i][1].location) + "
"; + if (special) + { + // :delmarks! only deletes a-z marks + for (var mark in localMarks) + removeLocalMark(mark); + } + else + { + var pattern = new RegExp("[" + filter.replace(/\s+/g, "") + "]"); + for (var mark in urlMarks) + { + if (pattern.test(mark)) + removeURLMark(mark); + } + for (var mark in localMarks) + { + if (pattern.test(mark)) + removeLocalMark(mark); + } + } + }, - vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); - } + jumpTo: function (mark) + { + var ok = false; + + if (isURLMark(mark)) + { + var slice = urlMarks[mark]; + if (slice && slice.tab && slice.tab.linkedBrowser) + { + if (!slice.tab.parentNode) + { + pendingJumps.push(slice); + // NOTE: this obviously won't work on generated pages using + // non-unique URLs, like Vimperator's help :( + vimperator.open(slice.location, vimperator.NEW_TAB); + return; + } + var index = vimperator.tabs.index(slice.tab); + if (index != -1) + { + vimperator.tabs.select(index); + var win = slice.tab.linkedBrowser.contentWindow; + if (win.location.href != slice.location) + { + pendingJumps.push(slice); + win.location.href = slice.location; + return; + } + vimperator.log("Jumping to URL mark: " + mark + " | " + slice.location + " | (" + slice.position.x + ", " + slice.position.y + ") | tab: " + vimperator.tabs.index(slice.tab), 5); + win.scrollTo(slice.position.x * win.scrollMaxX, slice.position.y * win.scrollMaxY); + ok = true; + } + } + } + else if (isLocalMark(mark)) + { + var win = window.content; + var slice = localMarks[mark] || []; + + for (var i = 0; i < slice.length; i++) + { + if (win.location.href == slice[i].location) + { + vimperator.log("Jumping to local mark: " + mark + " | " + slice[i].location + " | (" + slice[i].position.x + ", " + slice[i].position.y + ")", 5); + win.scrollTo(slice[i].position.x * win.scrollMaxX, slice[i].position.y * win.scrollMaxY); + ok = true; + } + } + } + + if (!ok) + vimperator.echoerr("E20: Mark not set"); // FIXME: move up? + }, + + list: function (filter) + { + var marks = getSortedMarks(); + + if (marks.length == 0) + { + vimperator.echoerr("No marks set"); + return; + } + + if (filter.length > 0) + { + marks = marks.filter(function (mark) { + if (filter.indexOf(mark[0]) > -1) + return mark; + }); + if (marks.length == 0) + { + vimperator.echoerr("E283: No marks matching \"" + filter + "\""); + return; + } + } + + var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + + ""; + for (var i = 0; i < marks.length; i++) + { + list += "" + + "" + + "" + + "" + + "" + + ""; + } + list += "
marklinecolfile
" + marks[i][0] + "" + Math.round(marks[i][1].position.y * 100) + "%" + Math.round(marks[i][1].position.x * 100) + "%" + vimperator.util.escapeHTML(marks[i][1].location) + "
"; + + vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); + } + + }; //}}} -} //}}} +}; //}}} vimperator.QuickMarks = function () //{{{ { @@ -781,103 +794,107 @@ vimperator.QuickMarks = function () //{{{ /////////////////////////////////////////////////////////////////////////////{{{ var qmarks = {}; - var saved_marks = vimperator.options.getPref("quickmarks", "").split("\n"); + var savedMarks = vimperator.options.getPref("quickmarks", "").split("\n"); // load the saved quickmarks -- TODO: change to sqlite - for (var i = 0; i < saved_marks.length - 1; i += 2) + for (var i = 0; i < savedMarks.length - 1; i += 2) { - qmarks[saved_marks[i]] = saved_marks[i + 1]; + qmarks[savedMarks[i]] = savedMarks[i + 1]; } /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - this.add = function (qmark, location) - { - qmarks[qmark] = location; - } + return { - this.remove = function (filter) - { - var pattern = new RegExp("[" + filter.replace(/\s+/g, "") + "]"); - - for (var qmark in qmarks) + add: function (qmark, location) { - if (pattern.test(qmark)) - delete qmarks[qmark]; - } - } + qmarks[qmark] = location; + }, - this.removeAll = function () - { - qmarks = {}; - } - - this.jumpTo = function (qmark, where) - { - var url = qmarks[qmark]; - - if (url) - vimperator.open(url, where); - else - vimperator.echoerr("E20: QuickMark not set"); - } - - this.list = function (filter) - { - var marks = []; - - // TODO: should we sort these in a-zA-Z0-9 order? - for (var mark in qmarks) - marks.push([mark, qmarks[mark]]); - marks.sort(); - - if (marks.length == 0) + remove: function (filter) { - vimperator.echoerr("No QuickMarks set"); - return; - } + var pattern = new RegExp("[" + filter.replace(/\s+/g, "") + "]"); - if (filter.length > 0) + for (var qmark in qmarks) + { + if (pattern.test(qmark)) + delete qmarks[qmark]; + } + }, + + removeAll: function () { - marks = marks.filter(function (mark) { - if (filter.indexOf(mark[0]) > -1) - return mark; - }); + qmarks = {}; + }, + + jumpTo: function (qmark, where) + { + var url = qmarks[qmark]; + + if (url) + vimperator.open(url, where); + else + vimperator.echoerr("E20: QuickMark not set"); + }, + + list: function (filter) + { + var marks = []; + + // TODO: should we sort these in a-zA-Z0-9 order? + for (var mark in qmarks) + marks.push([mark, qmarks[mark]]); + marks.sort(); + if (marks.length == 0) { - vimperator.echoerr("E283: No QuickMarks matching \"" + filter + "\""); + vimperator.echoerr("No QuickMarks set"); return; } - } - var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + - ""; - for (var i = 0; i < marks.length; i++) + if (filter.length > 0) + { + marks = marks.filter(function (mark) { + if (filter.indexOf(mark[0]) > -1) + return mark; + }); + if (marks.length == 0) + { + vimperator.echoerr("E283: No QuickMarks matching \"" + filter + "\""); + return; + } + } + + var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + + "
QuickMarkURL
"; + for (var i = 0; i < marks.length; i++) + { + list += ""; + } + list += "
QuickMarkURL
" + marks[i][0] + + "" + vimperator.util.escapeHTML(marks[i][1]) + "
"; + + vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); + }, + + destroy: function () { - list += " " + marks[i][0] + - "" + vimperator.util.escapeHTML(marks[i][1]) + ""; - } - list += ""; + // save the quickmarks + var savedQuickMarks = ""; - vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); - } + for (var i in qmarks) + { + savedQuickMarks += i + "\n"; + savedQuickMarks += qmarks[i] + "\n"; + } - this.destroy = function () - { - // save the quickmarks - var saved_qmarks = ""; - - for (var i in qmarks) - { - saved_qmarks += i + "\n"; - saved_qmarks += qmarks[i] + "\n"; + vimperator.options.setPref("quickmarks", savedQuickMarks); } - vimperator.options.setPref("quickmarks", saved_qmarks); - } + }; //}}} -} //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/buffers.js b/content/buffers.js index 44caa372..165649cb 100644 --- a/content/buffers.js +++ b/content/buffers.js @@ -31,24 +31,25 @@ vimperator.Buffer = function () //{{{ //////////////////////////////////////////////////////////////////////////////// ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ + // used for the "B" mapping to remember the last :buffer[!] command var lastBufferSwitchArgs = ""; var lastBufferSwitchSpecial = true; - var zoom_manager = ZoomManager.prototype.getInstance(); + var zoomManager = ZoomManager.prototype.getInstance(); const ZOOM_INTERVAL = 25; // initialize the zoom levels - zoom_manager.zoomFactors = [zoom_manager.MIN]; - for (var i = ZOOM_INTERVAL; i <= zoom_manager.MAX; i += ZOOM_INTERVAL) - zoom_manager.zoomFactors.push(i); + zoomManager.zoomFactors = [zoomManager.MIN]; + for (var i = ZOOM_INTERVAL; i <= zoomManager.MAX; i += ZOOM_INTERVAL) + zoomManager.zoomFactors.push(i); function setZoom(value) { try { - zoom_manager.textZoom = value; - vimperator.echo("Text zoom: " + zoom_manager.textZoom + "%"); + zoomManager.textZoom = value; + vimperator.echo("Text zoom: " + zoomManager.textZoom + "%"); // TODO: shouldn't this just recalculate hint coords, rather than // unsuccessfully attempt to reshow hints? i.e. isn't it just relying // on the recalculation side effect? -- djk @@ -57,7 +58,7 @@ vimperator.Buffer = function () //{{{ } catch (e) // Components.results.NS_ERROR_INVALID_ARG { - vimperator.echoerr("Zoom value out of range (" + zoom_manager.MIN + "-" + zoom_manager.MAX + ")"); + vimperator.echoerr("Zoom value out of range (" + zoomManager.MIN + "-" + zoomManager.MAX + ")"); } } @@ -66,11 +67,11 @@ vimperator.Buffer = function () //{{{ // get this added to ZoomManager function bumpZoomLevel(steps) { - var adjusted_zoom = zoom_manager.snap(zoom_manager.textZoom); - var current = zoom_manager.indexOf(adjusted_zoom); + var adjustedZoom = zoomManager.snap(zoomManager.textZoom); + var current = zoomManager.indexOf(adjustedZoom); var next = current + steps; - var start = 0, end = zoom_manager.zoomFactors.length - 1; + var start = 0, end = zoomManager.zoomFactors.length - 1; if ((current == start && steps < 0) || (current == end && steps > 0)) { @@ -83,7 +84,7 @@ vimperator.Buffer = function () //{{{ else if (next > end) next = end; - setZoom(zoom_manager.zoomFactors[next]); + setZoom(zoomManager.zoomFactors[next]); } function checkScrollYBounds(win, direction) @@ -116,581 +117,587 @@ vimperator.Buffer = function () //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - this.__defineGetter__("URL", function () - { - // TODO: .URL is not defined for XUL documents - //return window.content.document.URL; - return window.content.document.location.href; - }); + return { - this.__defineGetter__("pageHeight", function () - { - return window.content.innerHeight; - }); - - this.__defineGetter__("textZoom", function () - { - return zoom_manager.textZoom; - }); - - this.__defineSetter__("textZoom", function (value) - { - setZoom(value); - }); - - this.__defineGetter__("title", function () - { - return window.content.document.title; - }); - - // returns an XPathResult object - this.evaluateXPath = function (expression, doc, elem, ordered) - { - if (!doc) - doc = window.content.document; - if (!elem) - elem = doc; - - var result = doc.evaluate(expression, elem, - function lookupNamespaceURI(prefix) { - switch (prefix) { - case "xhtml": - return "http://www.w3.org/1999/xhtml"; - default: - return null; - } - }, - ordered ? XPathResult.ORDERED_NODE_SNAPSHOT_TYPE : XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, - null - ); - - return result; - }; - - this.list = function (fullmode) - { - if (fullmode) + get URL() { - // toggle the special buffer previw window - if (vimperator.bufferwindow.visible()) - { - vimperator.bufferwindow.hide(); - } - else - { - var items = vimperator.completion.get_buffer_completions(""); - vimperator.bufferwindow.show(items); - vimperator.bufferwindow.selectItem(getBrowser().mTabContainer.selectedIndex); - } - } - else + // TODO: .URL is not defined for XUL documents + //return window.content.document.URL; + return window.content.document.location.href; + }, + + get pageHeight() { - // TODO: move this to vimperator.buffers.get() - var items = vimperator.completion.get_buffer_completions(""); - var number, indicator, title, url; + return window.content.innerHeight; + }, - var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + ""; - for (var i = 0; i < items.length; i++) - { - if (i == vimperator.tabs.index()) - indicator = " % "; - else if (i == vimperator.tabs.index(vimperator.tabs.alternate)) - indicator = " # "; - else - indicator = " "; - - [number, title] = items[i][0].split(/:\s+/, 2); - url = items[i][1]; - url = vimperator.util.escapeHTML(url); - title = vimperator.util.escapeHTML(title); - - list += ""; - } - list += "
" + number + "" + indicator + - "" + title + - "" + url + "
"; - - vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); - } - }; - - this.scrollBottom = function () - { - scrollToPercentiles(-1, 100); - }; - - this.scrollColumns = function (cols) - { - var win = window.document.commandDispatcher.focusedWindow; - const COL_WIDTH = 20; - - if (cols > 0 && win.scrollX >= win.scrollMaxX || cols < 0 && win.scrollX == 0) - vimperator.beep(); - - win.scrollBy(COL_WIDTH * cols, 0); - }; - - this.scrollEnd = function () - { - scrollToPercentiles(100, -1); - }; - - this.scrollLines = function (lines) - { - var win = window.document.commandDispatcher.focusedWindow; - checkScrollYBounds(win, lines); - win.scrollByLines(lines); - }; - - this.scrollPages = function (pages) - { - var win = window.document.commandDispatcher.focusedWindow; - checkScrollYBounds(win, pages); - win.scrollByPages(pages); - }; - - this.scrollToPercentile = function (percentage) - { - scrollToPercentiles(-1, percentage); - }; - - this.scrollStart = function () - { - scrollToPercentiles(0, -1); - }; - - this.scrollTop = function () - { - scrollToPercentiles(-1, 0); - }; - - // TODO: allow callback for filtering out unwanted frames? User defined? - this.shiftFrameFocus = function (count, forward) - { - if (!window.content.document instanceof HTMLDocument) - return; - - var frames = []; - - // find all frames - depth-first search - (function (frame) + get textZoom() { - if (frame.document.body.localName.toLowerCase() == "body") - frames.push(frame); - for (var i = 0; i < frame.frames.length; i++) - arguments.callee(frame.frames[i]) - })(window.content); + return zoomManager.textZoom; + }, - if (frames.length == 0) // currently top is always included - return; - - // remove all unfocusable frames - // TODO: find a better way to do this - walking the tree is too slow - var start = document.commandDispatcher.focusedWindow; - frames = frames.filter(function (frame) { - frame.focus(); - if (document.commandDispatcher.focusedWindow == frame) - return frame; - }); - start.focus(); - - // find the currently focused frame index - // TODO: If the window is a frameset then the first _frame_ should be - // focused. Since this is not the current FF behaviour, - // we initalize current to -1 so the first call takes us to the - // first frame. - var current = -1; - for (var i = 0; i < frames.length; i++) + get textZoom(value) { - if (frames[i] == document.commandDispatcher.focusedWindow) - { - var current = i; - break; - } - } + setZoom(value); + }, - // calculate the next frame to focus - var next = current; - if (forward) + get title() { - if (count > 1) - next = current + count; - else - next++; + return window.content.document.title; + }, - if (next > frames.length - 1) - { - if (current == frames.length - 1) - vimperator.beep(); // still allow the frame indicator to be activated - - next = frames.length - 1; - } - } - else + // returns an XPathResult object + evaluateXPath: function (expression, doc, elem, ordered) { - if (count > 1) - next = current - count; - else - next--; + if (!doc) + doc = window.content.document; + if (!elem) + elem = doc; - if (next < 0) - { - if (current == 0) - vimperator.beep(); // still allow the frame indicator to be activated - - next = 0; - } - } - - // focus next frame and scroll into view - frames[next].focus(); - if (frames[next] != window.content) - frames[next].frameElement.scrollIntoView(false); - - // add the frame indicator - // TODO: make this an XBL element rather than messing with the content - // document - var doc = frames[next].document; - var indicator = doc.createElement("div"); - indicator.id = "vimperator-frame-indicator"; - // NOTE: need to set a high z-index - it's a crapshoot! - var style = "background-color: red; opacity: 0.5; z-index: 999;" + - "position: fixed; top: 0; bottom: 0; left: 0; right: 0;"; - indicator.setAttribute("style", style); - doc.body.appendChild(indicator); - - // remove the frame indicator - setTimeout(function () { doc.body.removeChild(indicator); }, 500); - }; - - // updates the buffer preview in place only if list is visible - this.updateBufferList = function () - { - if (!vimperator.bufferwindow.visible()) - return false; - - var items = vimperator.completion.get_buffer_completions(""); - vimperator.bufferwindow.show(items); - vimperator.bufferwindow.selectItem(getBrowser().mTabContainer.selectedIndex); - }; - - // XXX: should this be in v.buffers. or v.tabs.? - // "buffer" is a string which matches the URL or title of a buffer, if it - // is null, the last used string is used again - this.switchTo = function (buffer, allowNonUnique, count, reverse) - { - if (buffer != null) - { - // store this command, so it can be repeated with "B" - lastBufferSwitchArgs = buffer; - lastBufferSwitchSpecial = allowNonUnique; - } - else - { - buffer = lastBufferSwitchArgs; - if (typeof allowNonUnique == "undefined" || allowNonUnique == null) - allowNonUnique = lastBufferSwitchSpecial; - } - - if (!count || count < 1) - count = 1; - if (typeof reverse != "boolean") - reverse = false; - - var match; - if (match = buffer.match(/^(\d+):?/)) - return vimperator.tabs.select(parseInt(match[1], 10) - 1, false); // make it zero-based - - var matches = []; - var lower_buffer = buffer.toLowerCase(); - var first = vimperator.tabs.index() + (reverse ? 0 : 1); - for (var i = 0; i < getBrowser().browsers.length; i++) - { - var index = (i + first) % getBrowser().browsers.length; - var url = getBrowser().getBrowserAtIndex(index).contentDocument.location.href; - var title = getBrowser().getBrowserAtIndex(index).contentDocument.title.toLowerCase(); - if (url == buffer) - return vimperator.tabs.select(index, false); - - if (url.indexOf(buffer) >= 0 || title.indexOf(lower_buffer) >= 0) - matches.push(index); - } - if (matches.length == 0) - vimperator.echoerr("E94: No matching buffer for " + buffer); - else if (matches.length > 1 && !allowNonUnique) - vimperator.echoerr("E93: More than one match for " + buffer); - else - { - if (reverse) - { - index = matches.length - count; - while (index < 0) - index += matches.length; - } - else - index = (count - 1) % matches.length; - - vimperator.tabs.select(matches[index], false); - } - }; - - this.zoomIn = function (steps) - { - bumpZoomLevel(steps); - }; - - this.zoomOut = function (steps) - { - bumpZoomLevel(-steps); - }; - - this.pageInfo = function (verbose) - { - const feedTypes = { - "application/rss+xml": "RSS", - "application/atom+xml": "Atom", - "text/xml": "XML", - "application/xml": "XML", - "application/rdf+xml": "XML" - }; - - function isValidFeed(aData, aPrincipal, aIsFeed) - { - if (!aData || !aPrincipal) - return false; - - if (!aIsFeed) - { - var type = aData.type && aData.type.toLowerCase(); - type = type.replace(/^\s+|\s*(?:;.*)?$/g, ""); - - aIsFeed = (type == "application/rss+xml" || type == "application/atom+xml"); - if (!aIsFeed) + var result = doc.evaluate(expression, elem, + function lookupNamespaceURI(prefix) { - // really slimy: general XML types with magic letters in the title - const titleRegex = /(^|\s)rss($|\s)/i; - aIsFeed = ((type == "text/xml" || type == "application/rdf+xml" || - type == "application/xml") && titleRegex.test(aData.title)); + switch (prefix) + { + case "xhtml": + return "http://www.w3.org/1999/xhtml"; + default: + return null; + } + }, + ordered ? XPathResult.ORDERED_NODE_SNAPSHOT_TYPE : XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, + null + ); + + return result; + }, + + list: function (fullmode) + { + if (fullmode) + { + // toggle the special buffer previw window + if (vimperator.bufferwindow.visible()) + { + vimperator.bufferwindow.hide(); + } + else + { + var items = vimperator.completion.buffer(""); + vimperator.bufferwindow.show(items); + vimperator.bufferwindow.selectItem(getBrowser().mTabContainer.selectedIndex); + } + } + else + { + // TODO: move this to vimperator.buffers.get() + var items = vimperator.completion.buffer(""); + var number, indicator, title, url; + + var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
" + ""; + for (var i = 0; i < items.length; i++) + { + if (i == vimperator.tabs.index()) + indicator = " % "; + else if (i == vimperator.tabs.index(vimperator.tabs.alternate)) + indicator = " # "; + else + indicator = " "; + + [number, title] = items[i][0].split(/:\s+/, 2); + url = items[i][1]; + url = vimperator.util.escapeHTML(url); + title = vimperator.util.escapeHTML(title); + + list += ""; + } + list += "
" + number + "" + indicator + + "" + title + + "" + url + "
"; + + vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); + } + }, + + scrollBottom: function () + { + scrollToPercentiles(-1, 100); + }, + + scrollColumns: function (cols) + { + var win = window.document.commandDispatcher.focusedWindow; + const COL_WIDTH = 20; + + if (cols > 0 && win.scrollX >= win.scrollMaxX || cols < 0 && win.scrollX == 0) + vimperator.beep(); + + win.scrollBy(COL_WIDTH * cols, 0); + }, + + scrollEnd: function () + { + scrollToPercentiles(100, -1); + }, + + scrollLines: function (lines) + { + var win = window.document.commandDispatcher.focusedWindow; + checkScrollYBounds(win, lines); + win.scrollByLines(lines); + }, + + scrollPages: function (pages) + { + var win = window.document.commandDispatcher.focusedWindow; + checkScrollYBounds(win, pages); + win.scrollByPages(pages); + }, + + scrollToPercentile: function (percentage) + { + scrollToPercentiles(-1, percentage); + }, + + scrollStart: function () + { + scrollToPercentiles(0, -1); + }, + + scrollTop: function () + { + scrollToPercentiles(-1, 0); + }, + + // TODO: allow callback for filtering out unwanted frames? User defined? + shiftFrameFocus: function (count, forward) + { + if (!window.content.document instanceof HTMLDocument) + return; + + var frames = []; + + // find all frames - depth-first search + (function (frame) + { + if (frame.document.body.localName.toLowerCase() == "body") + frames.push(frame); + for (var i = 0; i < frame.frames.length; i++) + arguments.callee(frame.frames[i]); + })(window.content); + + if (frames.length == 0) // currently top is always included + return; + + // remove all unfocusable frames + // TODO: find a better way to do this - walking the tree is too slow + var start = document.commandDispatcher.focusedWindow; + frames = frames.filter(function (frame) { + frame.focus(); + if (document.commandDispatcher.focusedWindow == frame) + return frame; + }); + start.focus(); + + // find the currently focused frame index + // TODO: If the window is a frameset then the first _frame_ should be + // focused. Since this is not the current FF behaviour, + // we initalize current to -1 so the first call takes us to the + // first frame. + var current = -1; + for (var i = 0; i < frames.length; i++) + { + if (frames[i] == document.commandDispatcher.focusedWindow) + { + var current = i; + break; } } - if (aIsFeed) + // calculate the next frame to focus + var next = current; + if (forward) + { + if (count > 1) + next = current + count; + else + next++; + + if (next > frames.length - 1) + { + if (current == frames.length - 1) + vimperator.beep(); // still allow the frame indicator to be activated + + next = frames.length - 1; + } + } + else + { + if (count > 1) + next = current - count; + else + next--; + + if (next < 0) + { + if (current == 0) + vimperator.beep(); // still allow the frame indicator to be activated + + next = 0; + } + } + + // focus next frame and scroll into view + frames[next].focus(); + if (frames[next] != window.content) + frames[next].frameElement.scrollIntoView(false); + + // add the frame indicator + // TODO: make this an XBL element rather than messing with the content + // document + var doc = frames[next].document; + var indicator = doc.createElement("div"); + indicator.id = "vimperator-frame-indicator"; + // NOTE: need to set a high z-index - it's a crapshoot! + var style = "background-color: red; opacity: 0.5; z-index: 999;" + + "position: fixed; top: 0; bottom: 0; left: 0; right: 0;"; + indicator.setAttribute("style", style); + doc.body.appendChild(indicator); + + // remove the frame indicator + setTimeout(function () { doc.body.removeChild(indicator); }, 500); + }, + + // updates the buffer preview in place only if list is visible + updateBufferList: function () + { + if (!vimperator.bufferwindow.visible()) + return false; + + var items = vimperator.completion.buffer(""); + vimperator.bufferwindow.show(items); + vimperator.bufferwindow.selectItem(getBrowser().mTabContainer.selectedIndex); + }, + + // XXX: should this be in v.buffers. or v.tabs.? + // "buffer" is a string which matches the URL or title of a buffer, if it + // is null, the last used string is used again + switchTo: function (buffer, allowNonUnique, count, reverse) + { + if (buffer != null) + { + // store this command, so it can be repeated with "B" + lastBufferSwitchArgs = buffer; + lastBufferSwitchSpecial = allowNonUnique; + } + else + { + buffer = lastBufferSwitchArgs; + if (typeof allowNonUnique == "undefined" || allowNonUnique == null) + allowNonUnique = lastBufferSwitchSpecial; + } + + if (!count || count < 1) + count = 1; + if (typeof reverse != "boolean") + reverse = false; + + var match; + if (match = buffer.match(/^(\d+):?/)) + return vimperator.tabs.select(parseInt(match[1], 10) - 1, false); // make it zero-based + + var matches = []; + var lowerBuffer = buffer.toLowerCase(); + var first = vimperator.tabs.index() + (reverse ? 0 : 1); + for (var i = 0; i < getBrowser().browsers.length; i++) + { + var index = (i + first) % getBrowser().browsers.length; + var url = getBrowser().getBrowserAtIndex(index).contentDocument.location.href; + var title = getBrowser().getBrowserAtIndex(index).contentDocument.title.toLowerCase(); + if (url == buffer) + return vimperator.tabs.select(index, false); + + if (url.indexOf(buffer) >= 0 || title.indexOf(lowerBuffer) >= 0) + matches.push(index); + } + if (matches.length == 0) + vimperator.echoerr("E94: No matching buffer for " + buffer); + else if (matches.length > 1 && !allowNonUnique) + vimperator.echoerr("E93: More than one match for " + buffer); + else + { + if (reverse) + { + index = matches.length - count; + while (index < 0) + index += matches.length; + } + else + index = (count - 1) % matches.length; + + vimperator.tabs.select(matches[index], false); + } + }, + + zoomIn: function (steps) + { + bumpZoomLevel(steps); + }, + + zoomOut: function (steps) + { + bumpZoomLevel(-steps); + }, + + pageInfo: function (verbose) + { + const feedTypes = { + "application/rss+xml": "RSS", + "application/atom+xml": "Atom", + "text/xml": "XML", + "application/xml": "XML", + "application/rdf+xml": "XML" + }; + + function isValidFeed(aData, aPrincipal, aIsFeed) + { + if (!aData || !aPrincipal) + return false; + + if (!aIsFeed) + { + var type = aData.type && aData.type.toLowerCase(); + type = type.replace(/^\s+|\s*(?:;.*)?$/g, ""); + + aIsFeed = (type == "application/rss+xml" || type == "application/atom+xml"); + if (!aIsFeed) + { + // really slimy: general XML types with magic letters in the title + const titleRegex = /(^|\s)rss($|\s)/i; + aIsFeed = ((type == "text/xml" || type == "application/rdf+xml" || + type == "application/xml") && titleRegex.test(aData.title)); + } + } + + if (aIsFeed) + { + try + { + urlSecurityCheck(aData.href, aPrincipal, + Components.interfaces.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL); + } + catch (ex) + { + aIsFeed = false; + } + } + + if (type) + aData.type = type; + + return aIsFeed; + } + + // TODO: could this be useful for other commands? + function createTable(data) + { + var ret = ""; + + if (data.length - 1) + { + for (var i = 0; i < data.length - 1 ; i++) + ret += ""; + } + else + { + ret += ""; + } + + return ret + "
" + + data[data.length - 1][0] + "
" + data[i][0] + ": " + data[i][1] + "
(" + data[data.length - 1][1] + ")
"; + } + + var pageGeneral = []; + var pageFeeds = []; + var pageMeta = []; + + // get file size + const nsICacheService = Components.interfaces.nsICacheService; + const ACCESS_READ = Components.interfaces.nsICache.ACCESS_READ; + const cacheService = Components.classes["@mozilla.org/network/cache-service;1"].getService(nsICacheService); + var httpCacheSession = cacheService.createSession("HTTP", 0, true); + var ftpCacheSession = cacheService.createSession("FTP", 0, true); + httpCacheSession.doomEntriesIfExpired = false; + ftpCacheSession.doomEntriesIfExpired = false; + var cacheKey = window.content.document.location.toString().replace(/#.*$/, ""); + try + { + var cacheEntryDescriptor = httpCacheSession.openCacheEntry(cacheKey, ACCESS_READ, false); + } + catch (ex) { try { - urlSecurityCheck(aData.href, aPrincipal, - Components.interfaces.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL); - } - catch (ex) - { - aIsFeed = false; + cacheEntryDescriptor = ftpCacheSession.openCacheEntry(cacheKey, ACCESS_READ, false); } + catch (ex2) { } } - if (type) - aData.type = type; - - return aIsFeed; - } - - // TODO: could this be useful for other commands? - function createTable(data) - { - var ret = ""; - - if (data.length - 1) + var pageSize = []; // [0] bytes; [1] kbytes + if (cacheEntryDescriptor) { - for (var i = 0; i < data.length - 1 ; i++) - ret += ""; - } - else - { - ret += ""; + pageSize[0] = vimperator.util.formatBytes(cacheEntryDescriptor.dataSize, 0, false); + pageSize[1] = vimperator.util.formatBytes(cacheEntryDescriptor.dataSize, 2, true); + if (pageSize[1] == pageSize[0]) + pageSize[1] = null; // don't output "xx Bytes" twice } - return ret + "
" + - data[data.length - 1][0] + "
" + data[i][0] + ": " + data[i][1] + "
(" + data[data.length - 1][1] + ")
"; - } - - var pageGeneral = []; - var pageFeeds = []; - var pageMeta = []; - - // get file size - const nsICacheService = Components.interfaces.nsICacheService; - const ACCESS_READ = Components.interfaces.nsICache.ACCESS_READ; - const cacheService = Components.classes["@mozilla.org/network/cache-service;1"].getService(nsICacheService); - var httpCacheSession = cacheService.createSession("HTTP", 0, true); - var ftpCacheSession = cacheService.createSession("FTP", 0, true); - httpCacheSession.doomEntriesIfExpired = false; - ftpCacheSession.doomEntriesIfExpired = false; - var cacheKey = window.content.document.location.toString().replace(/#.*$/, ""); - try - { - var cacheEntryDescriptor = httpCacheSession.openCacheEntry(cacheKey, ACCESS_READ, false); - } - catch (ex) - { - try - { - cacheEntryDescriptor = ftpCacheSession.openCacheEntry(cacheKey, ACCESS_READ, false); - } - catch (ex2) { } - } - - var pageSize = []; // [0] bytes; [1] kbytes - if (cacheEntryDescriptor) - { - pageSize[0] = vimperator.util.formatBytes(cacheEntryDescriptor.dataSize, 0, false); - pageSize[1] = vimperator.util.formatBytes(cacheEntryDescriptor.dataSize, 2, true); - if (pageSize[1] == pageSize[0]) - pageSize[1] = null; // don't output "xx Bytes" twice - } - - // put feeds rss into pageFeeds[] - var linkNodes = window.content.document.getElementsByTagName("link"); - var length = linkNodes.length; - for (var i = 0; i < length; i++) - { - var link = linkNodes[i]; - if (!link.href) - continue; - - var rel = link.rel && link.rel.toLowerCase(); - var rels = {}; - if (rel) - { - for each (let relVal in rel.split(/\s+/)) - rels[relVal] = true; - } - - if (rels.feed || (link.type && rels.alternate && !rels.stylesheet)) - { - var feed = { title: link.title, href: link.href, type: link.type || "" }; - if (isValidFeed(feed, window.content.document.nodePrincipal, rels.feed)) - { - var type = feedTypes[feed.type] || feedTypes["application/rss+xml"]; - pageFeeds.push([feed.title, vimperator.util.highlightURL(feed.href, true) + " (" + type + ")"]); - } - } - } - - var lastModVerbose = new Date(window.content.document.lastModified).toLocaleString(); - var lastMod = new Date(window.content.document.lastModified).toLocaleFormat("%x %X"); - // FIXME: probably unportable across differnet language versions - if (lastModVerbose == "Invalid Date") - lastModVerbose = lastMod = null; - - // Ctrl-g single line output - if (!verbose) - { - var info = []; // tmp array for joining later - var file = window.content.document.location.pathname.split("/").pop() || "[No Name]"; - var title = window.content.document.title || "[No Title]"; - - if (pageSize[0]) - info.push(pageSize[1] || pageSize[0]); - - if (lastMod) - info.push(lastMod); - - var countFeeds = ""; - if (pageFeeds.length) - countFeeds = pageFeeds.length + (pageFeeds.length == 1 ? " feed" : " feeds"); - - if (countFeeds) - info.push(countFeeds); - - var pageInfoText = '"' + file + '" [' + info.join(", ") + "] " + title; - vimperator.echo(pageInfoText, vimperator.commandline.FORCE_SINGLELINE); - return; - } - - // get general infos - pageGeneral.push(["Title", window.content.document.title]); - pageGeneral.push(["URL", vimperator.util.highlightURL(window.content.document.location.toString(), true)]); - - var ref = "referrer" in window.content.document && window.content.document.referrer; - if (ref) - pageGeneral.push(["Referrer", vimperator.util.highlightURL(ref, true)]); - - if (pageSize[0]) - { - if (pageSize[1]) - pageGeneral.push(["File Size", pageSize[1] + " (" + pageSize[0] + ")"]); - else - pageGeneral.push(["File Size", pageSize[0]]); - } - - pageGeneral.push(["Mime-Type", content.document.contentType]); - pageGeneral.push(["Encoding", content.document.characterSet]); - pageGeneral.push(["Compatibility", content.document.compatMode == "BackCompat" ? "Quirks Mode" : "Full/Almost Standards Mode"]); - if (lastModVerbose) - pageGeneral.push(["Last Modified", lastModVerbose]); - - // get meta tag data, sort and put into pageMeta[] - var metaNodes = window.content.document.getElementsByTagName("meta"); - var length = metaNodes.length; - if (length) - { - var tmpSort = []; - var tmpDict = []; - + // put feeds rss into pageFeeds[] + var linkNodes = window.content.document.getElementsByTagName("link"); + var length = linkNodes.length; for (var i = 0; i < length; i++) { - var tmpTag = metaNodes[i].name || metaNodes[i].httpEquiv;// + - var tmpTagNr = tmpTag + "-" + i; // allows multiple (identical) meta names - tmpDict[tmpTagNr] = [tmpTag, metaNodes[i].content]; - tmpSort.push(tmpTagNr); // array for sorting + var link = linkNodes[i]; + if (!link.href) + continue; + + var rel = link.rel && link.rel.toLowerCase(); + var rels = {}; + if (rel) + { + for each (let relVal in rel.split(/\s+/)) + rels[relVal] = true; + } + + if (rels.feed || (link.type && rels.alternate && !rels.stylesheet)) + { + var feed = { title: link.title, href: link.href, type: link.type || "" }; + if (isValidFeed(feed, window.content.document.nodePrincipal, rels.feed)) + { + var type = feedTypes[feed.type] || feedTypes["application/rss+xml"]; + pageFeeds.push([feed.title, vimperator.util.highlightURL(feed.href, true) + " (" + type + ")"]); + } + } } - // sort: ignore-case - tmpSort.sort(function (a,b){return a.toLowerCase() > b.toLowerCase() ? 1 : -1;}); - for (var i=0; i < tmpSort.length; i++) - pageMeta.push([tmpDict[tmpSort[i]][0], vimperator.util.highlightURL(tmpDict[tmpSort[i]][1], false)]); - } + var lastModVerbose = new Date(window.content.document.lastModified).toLocaleString(); + var lastMod = new Date(window.content.document.lastModified).toLocaleFormat("%x %X"); + // FIXME: probably unportable across differnet language versions + if (lastModVerbose == "Invalid Date") + lastModVerbose = lastMod = null; - pageMeta.push(["Meta Tags", ""]); // add extra text to the end - pageGeneral.push(["General Info", ""]); - pageFeeds.push(["Feeds", ""]); - - var pageInfoText = ""; - var option = vimperator.options["pageinfo"]; - var br = ""; - - for (var z = 0; z < option.length; z++) - { - switch (option[z]) + // Ctrl-g single line output + if (!verbose) { - case "g": - if (pageGeneral.length > 1) - { - pageInfoText += br + createTable(pageGeneral); - if (!br) - br = "
"; - } - break; - case "f": - if (pageFeeds.length > 1) - { - pageInfoText += br + createTable(pageFeeds); - if (!br) - br = "
"; - } - break; - case "m": - if (pageMeta.length > 1) - { - pageInfoText += br + createTable(pageMeta); - if (!br) - br = "
"; - } - break; + var info = []; // tmp array for joining later + var file = window.content.document.location.pathname.split("/").pop() || "[No Name]"; + var title = window.content.document.title || "[No Title]"; + + if (pageSize[0]) + info.push(pageSize[1] || pageSize[0]); + + if (lastMod) + info.push(lastMod); + + var countFeeds = ""; + if (pageFeeds.length) + countFeeds = pageFeeds.length + (pageFeeds.length == 1 ? " feed" : " feeds"); + + if (countFeeds) + info.push(countFeeds); + + var pageInfoText = '"' + file + '" [' + info.join(", ") + "] " + title; + vimperator.echo(pageInfoText, vimperator.commandline.FORCE_SINGLELINE); + return; } + + // get general infos + pageGeneral.push(["Title", window.content.document.title]); + pageGeneral.push(["URL", vimperator.util.highlightURL(window.content.document.location.toString(), true)]); + + var ref = "referrer" in window.content.document && window.content.document.referrer; + if (ref) + pageGeneral.push(["Referrer", vimperator.util.highlightURL(ref, true)]); + + if (pageSize[0]) + { + if (pageSize[1]) + pageGeneral.push(["File Size", pageSize[1] + " (" + pageSize[0] + ")"]); + else + pageGeneral.push(["File Size", pageSize[0]]); + } + + pageGeneral.push(["Mime-Type", content.document.contentType]); + pageGeneral.push(["Encoding", content.document.characterSet]); + pageGeneral.push(["Compatibility", content.document.compatMode == "BackCompat" ? "Quirks Mode" : "Full/Almost Standards Mode"]); + if (lastModVerbose) + pageGeneral.push(["Last Modified", lastModVerbose]); + + // get meta tag data, sort and put into pageMeta[] + var metaNodes = window.content.document.getElementsByTagName("meta"); + var length = metaNodes.length; + if (length) + { + var tmpSort = []; + var tmpDict = []; + + for (var i = 0; i < length; i++) + { + var tmpTag = metaNodes[i].name || metaNodes[i].httpEquiv;// + + var tmpTagNr = tmpTag + "-" + i; // allows multiple (identical) meta names + tmpDict[tmpTagNr] = [tmpTag, metaNodes[i].content]; + tmpSort.push(tmpTagNr); // array for sorting + } + + // sort: ignore-case + tmpSort.sort(function (a,b){return a.toLowerCase() > b.toLowerCase() ? 1 : -1;}); + for (var i = 0; i < tmpSort.length; i++) + pageMeta.push([tmpDict[tmpSort[i]][0], vimperator.util.highlightURL(tmpDict[tmpSort[i]][1], false)]); + } + + pageMeta.push(["Meta Tags", ""]); // add extra text to the end + pageGeneral.push(["General Info", ""]); + pageFeeds.push(["Feeds", ""]); + + var pageInfoText = ""; + var option = vimperator.options["pageinfo"]; + var br = ""; + + for (var z = 0; z < option.length; z++) + { + switch (option[z]) + { + case "g": + if (pageGeneral.length > 1) + { + pageInfoText += br + createTable(pageGeneral); + if (!br) + br = "
"; + } + break; + case "f": + if (pageFeeds.length > 1) + { + pageInfoText += br + createTable(pageFeeds); + if (!br) + br = "
"; + } + break; + case "m": + if (pageMeta.length > 1) + { + pageInfoText += br + createTable(pageMeta); + if (!br) + br = "
"; + } + break; + } + } + vimperator.echo(pageInfoText, vimperator.commandline.FORCE_MULTILINE); } - vimperator.echo(pageInfoText, vimperator.commandline.FORCE_MULTILINE); + }; //}}} -} //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/commands.js b/content/commands.js index 1f1a6f9e..d9126474 100644 --- a/content/commands.js +++ b/content/commands.js @@ -26,7 +26,7 @@ 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.Command = function (specs, action, extra_info) //{{{ +vimperator.Command = function (specs, action, extraInfo) //{{{ { if (!specs || !action) return null; @@ -36,63 +36,63 @@ vimperator.Command = function (specs, action, extra_info) //{{{ // 'abc', 'abcdef' var parseSpecs = function (specs) { - var short_names = []; - var long_names = []; + var shortNames = []; + var longNames = []; var names = []; for (var i = 0; i < specs.length; i++) { var match; if (match = specs[i].match(/(\w+|!)\[(\w+)\]/)) { - short_names.push(match[1]); - long_names.push(match[1] + match[2]); + shortNames.push(match[1]); + longNames.push(match[1] + match[2]); // order as long1, short1, long2, short2 names.push(match[1] + match[2]); names.push(match[1]); } else { - long_names.push(specs[i]); + longNames.push(specs[i]); names.push(specs[i]); } } - return { names: names, long_names: long_names, short_names: short_names }; - } + return { names: names, longNames: longNames, shortNames: shortNames }; + }; this.specs = specs; - var expanded_specs = parseSpecs(specs); - this.short_names = expanded_specs.short_names; - this.long_names = expanded_specs.long_names; + var expandedSpecs = parseSpecs(specs); + this.shortNames = expandedSpecs.shortNames; + this.longNames = expandedSpecs.longNames; // return the primary command name (the long name of the first spec listed) - this.name = this.long_names[0]; + this.name = this.longNames[0]; // return all command name aliases - this.names = expanded_specs.names; + this.names = expandedSpecs.names; this.action = action; // TODO: build a better default usage string this.usage = [this.specs[0]]; - if (extra_info) + if (extraInfo) { - //var flags = extra_info.flags || 0; + //var flags = extraInfo.flags || 0; - if (extra_info.usage) - this.usage = extra_info.usage; + if (extraInfo.usage) + this.usage = extraInfo.usage; - this.help = extra_info.help || null; - this.short_help = extra_info.short_help || null; - this.completer = extra_info.completer || null; + this.help = extraInfo.help || null; + this.shortHelp = extraInfo.shortHelp || null; + this.completer = extraInfo.completer || null; } -} +}; vimperator.Command.prototype.execute = function (args, special, count, modifiers) { this.action.call(this, args, special, count, modifiers); -} +}; // return true if the candidate name matches one of the command's aliases // (including all acceptable abbreviations) @@ -123,7 +123,7 @@ vimperator.Command.prototype.hasName = function (name) } } return false; -} +}; //}}} vimperator.Commands = function () //{{{ @@ -132,22 +132,13 @@ vimperator.Commands = function () //{{{ ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - var ex_commands = []; - var last_run_command = ""; // updated whenever the users runs a command with :! - - function addDefaultCommand(command) - { - ex_commands.push(command); - vimperator.Commands.prototype[command.name] = function (args, special, count, modifiers) - { - command.execute(args, special, count, modifiers); - } - } + var exCommands = []; + var lastRunCommand = ""; // updated whenever the users runs a command with :! function commandsIterator() { - for (var i = 0; i < ex_commands.length; i++) - yield ex_commands[i]; + for (var i = 0; i < exCommands.length; i++) + yield exCommands[i]; throw StopIteration; } @@ -156,87 +147,90 @@ vimperator.Commands = function () //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - this.__iterator__ = function () - { - return commandsIterator(); - } + var commandManager = { - this.add = function (command) - { - if (!command) - return false; - - ex_commands.push(command); - - return true; - } - - this.get = function (name) - { - for (var i = 0; i < ex_commands.length; i++) + __iterator__: function () { - if (ex_commands[i].hasName(name)) - return ex_commands[i]; - } + return commandsIterator(); + }, - return null; - } - - // TODO: generalized 0 count handling -> "Zero count" - // FIXME: doesn't really belong here... - // return [null, null, null, null, heredoc_tag || false]; - // [count, cmd, special, args] = match; - this.parseCommand = function (str, tag) - { - // remove comments - str.replace(/\s*".*$/, ""); - - if (tag) // we already have a multiline heredoc construct + add: function (command) { - if (str == tag) - return [null, null, null, null, false]; + this[command.name] = function (args, special, count, modifiers) + { + command.execute(args, special, count, modifiers); + }; + exCommands.push(command); + }, + + get: function (name) + { + for (var i = 0; i < exCommands.length; i++) + { + if (exCommands[i].hasName(name)) + return exCommands[i]; + } + + return null; + }, + + // TODO: generalized 0 count handling -> "Zero count" + // FIXME: doesn't really belong here... + // return [null, null, null, null, heredoc_tag || false]; + // [count, cmd, special, args] = match; + parseCommand: function (str, tag) + { + // remove comments + str.replace(/\s*".*$/, ""); + + if (tag) // we already have a multiline heredoc construct + { + if (str == tag) + return [null, null, null, null, false]; + else + return [null, null, null, str, tag]; + } + + // 0 - count, 1 - cmd, 2 - special, 3 - args, 4 - heredoc tag + var matches = str.match(/^:*(\d+)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/); + if (!matches) + return [null, null, null, null, null]; + matches.shift(); + + // parse count + if (matches[0]) + matches[0] = parseInt(matches[0], 10); else - return [null, null, null, str, tag]; + matches[0] = -1; + + matches[2] = !!matches[2]; + matches.push(null); + if (matches[3]) + { + tag = matches[3].match(/<<\s*(\w+)\s*$/); + if (tag && tag[1]) + matches[4] = tag[1]; + } + else + matches[3] = ""; + + return matches; } - // 0 - count, 1 - cmd, 2 - special, 3 - args, 4 - heredoc tag - var matches = str.match(/^:*(\d+)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/); - if (!matches) - return [null, null, null, null, null]; - matches.shift(); - - // parse count - if (matches[0]) - matches[0] = parseInt(matches[0], 10); - else - matches[0] = -1; - - matches[2] = !!matches[2]; - matches.push(null); - if (matches[3]) - { - tag = matches[3].match(/<<\s*(\w+)\s*$/); - if (tag && tag[1]) - matches[4] = tag[1]; - } - else - matches[3] = ""; - - return matches; - } + }; /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// DEFAULT COMMANDS //////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - addDefaultCommand(new vimperator.Command(["addo[ns]"], + commandManager.add(new vimperator.Command(["addo[ns]"], function () { vimperator.open("chrome://mozapps/content/extensions/extensions.xul", vimperator.NEW_TAB); }, { - short_help: "Show available Browser Extensions and Themes", + shortHelp: "Show available Browser Extensions and Themes", help: "You can add/remove/disable browser extensions from this dialog.
Be aware that not all Firefox extensions work, because Vimperator overrides some key bindings and changes Firefox's GUI." } )); - addDefaultCommand(new vimperator.Command(["ba[ck]"], + commandManager.add(new vimperator.Command(["ba[ck]"], function (args, special, count) { if (special) @@ -260,7 +254,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["[count]ba[ck][!] [url]"], - short_help: "Go back in the browser history", + shortHelp: "Go back in the browser history", help: "Count is supported, :3back goes back 3 pages in the browser history.
" + "The special version :back! goes to the beginning of the browser history.", completer: function (filter) @@ -279,22 +273,22 @@ vimperator.Commands = function () //{{{ } } )); - addDefaultCommand(new vimperator.Command(["bd[elete]", "bw[ipeout]", "bun[load]", "tabc[lose]"], + commandManager.add(new vimperator.Command(["bd[elete]", "bw[ipeout]", "bun[load]", "tabc[lose]"], function (args, special, count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count > 0 ? count : 1, special, 0); }, { usage: ["[count]bd[elete][!]"], - short_help: "Delete current buffer (=tab)", + shortHelp: "Delete current buffer (=tab)", help: "Count is supported, :2bd removes two tabs and the one to the right is selected. " + "Do :bdelete! to select the tab to the left after removing the current tab." } )); - addDefaultCommand(new vimperator.Command(["beep"], + commandManager.add(new vimperator.Command(["beep"], function () { vimperator.beep(); }, { - short_help: "Play a system beep" + shortHelp: "Play a system beep" } )); - addDefaultCommand(new vimperator.Command(["bma[rk]"], + commandManager.add(new vimperator.Command(["bma[rk]"], // takes: -t "foo" myurl // converts that string to a useful url and title, and calls addBookmark function (args) @@ -325,7 +319,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["bma[rk] [-t {title}] [url]"], - short_help: "Add a bookmark", + shortHelp: "Add a bookmark", help: "If you don't add a custom title, either the title of the web page or the URL is taken as the title.
" + "You can omit the optional [url] argument, so just do :bmark to bookmark the currently loaded web page with a default title and without any tags.
" + " -t \"custom title\"
" + @@ -335,32 +329,32 @@ vimperator.Commands = function () //{{{ "Tags WILL be some mechanism to classify bookmarks. Assume, you tag a URL with the tags \"linux\" and \"computer\" you'll be able to search for bookmarks containing these tags." } )); - addDefaultCommand(new vimperator.Command(["bmarks"], + commandManager.add(new vimperator.Command(["bmarks"], function (args, special) { vimperator.bookmarks.list(args, special); }, { usage: ["bmarks [filter]", "bmarks!"], - short_help: "Show bookmarks", + shortHelp: "Show bookmarks", help: "Open the message window at the bottom of the screen with all bookmarks which match [filter] either in the title or URL.
" + "The special version :bmarks! opens the default Firefox bookmarks window.
" + "The following options WILL be interpreted in the future:
" + " -T comma,separated,tag,list
", - completer: function (filter) { return vimperator.completion.get_bookmark_completions(filter); } + completer: function (filter) { return vimperator.completion.bookmark(filter); } } )); - addDefaultCommand(new vimperator.Command(["b[uffer]"], + commandManager.add(new vimperator.Command(["b[uffer]"], function (args, special) { vimperator.buffer.switchTo(args, special); }, { usage: ["b[uffer][!] {url|index}"], - short_help: "Go to buffer from buffer list", + shortHelp: "Go to buffer from buffer list", help: "Argument can be either the buffer index or the full URL.
" + "If argument is neither a full URL nor an index but uniquely identifies a buffer, " + "it is selected. With [!] the next buffer matching the argument " + "is selected, even if it cannot be identified uniquely.
" + "Use b as a shortcut to open this prompt.", - completer: function (filter) { return vimperator.completion.get_buffer_completions(filter); } + completer: function (filter) { return vimperator.completion.buffer(filter); } } )); - addDefaultCommand(new vimperator.Command(["buffers", "files", "ls", "tabs"], + commandManager.add(new vimperator.Command(["buffers", "files", "ls", "tabs"], function (args, special) { if (args) @@ -373,12 +367,12 @@ vimperator.Commands = function () //{{{ }, { usage: ["buffers[!]"], - short_help: "Show a list of all buffers (=tabs)", + shortHelp: "Show a list of all buffers (=tabs)", help: "The special version :buffers! opens the buffer list in a persistent preview window. " + "Call the special version of this command again to close the window." } )); - addDefaultCommand(new vimperator.Command(["delbm[arks]"], + commandManager.add(new vimperator.Command(["delbm[arks]"], function (args, special) { var result = vimperator.bookmarks.parseBookmarkString(args); @@ -388,8 +382,8 @@ vimperator.Commands = function () //{{{ if (result.url == null) result.url = vimperator.buffer.URL; - var deleted_count = vimperator.bookmarks.remove(result.url); - vimperator.echo(deleted_count + " bookmark(s) with url `" + result.url + "' deleted"); + var deletedCount = vimperator.bookmarks.remove(result.url); + vimperator.echo(deletedCount + " bookmark(s) with url `" + result.url + "' deleted"); } else { @@ -398,15 +392,15 @@ vimperator.Commands = function () //{{{ }, { usage: ["delbm[arks] {url}"], - short_help: "Delete a bookmark", + shortHelp: "Delete a bookmark", help: "Deletes all bookmarks which match the {url}. Use <Tab> key on a string to complete the URL which you want to delete.
" + "The following options WILL be interpreted in the future:
" + " [!] a special version to delete ALL bookmarks
" + " -T comma,separated,tag,list
", - completer: function (filter) { return vimperator.completion.get_bookmark_completions(filter); } + completer: function (filter) { return vimperator.completion.bookmark(filter); } } )); - addDefaultCommand(new vimperator.Command(["delm[arks]"], + commandManager.add(new vimperator.Command(["delm[arks]"], function (args, special) { if (!special && !args) @@ -451,7 +445,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["delm[arks] {marks}", "delm[arks]!"], - short_help: "Delete the specified marks", + shortHelp: "Delete the specified marks", help: "Marks are presented as a list. Example:
" + ":delmarks Aa b p deletes marks A, a, b and p
" + ":delmarks b-p deletes all marks in the range b to p
" + @@ -459,7 +453,7 @@ vimperator.Commands = function () //{{{ } )); - addDefaultCommand(new vimperator.Command(["delqm[arks]"], + commandManager.add(new vimperator.Command(["delqm[arks]"], function (args, special) { // TODO: finish arg parsing - we really need a proper way to do this. :) @@ -481,17 +475,17 @@ vimperator.Commands = function () //{{{ }, { usage: ["delqm[arks] {marks}", "delqm[arks]!"], - short_help: "Delete the specified QuickMarks", + shortHelp: "Delete the specified QuickMarks", help: "QuickMarks are presented as a list. Example:
" + ":delqmarks Aa b p deletes QuickMarks A, a, b and p
" + ":delqmarks b-p deletes all QuickMarks in the range b to p
" + ":delqmarks! deletes all QuickMarks" } )); - addDefaultCommand(new vimperator.Command(["downl[oads]", "dl"], + commandManager.add(new vimperator.Command(["downl[oads]", "dl"], function () { vimperator.open("chrome://mozapps/content/downloads/downloads.xul", vimperator.NEW_TAB); }, { - short_help: "Show progress of current downloads", + shortHelp: "Show progress of current downloads", help: "Open the original Firefox download dialog in a new tab.
" + "Here, downloads can be paused, canceled and resumed." } @@ -524,7 +518,7 @@ vimperator.Commands = function () //{{{ return arg; } - addDefaultCommand(new vimperator.Command(["ec[ho]"], + commandManager.add(new vimperator.Command(["ec[ho]"], function (args) { var res = argToString(args, true); @@ -533,14 +527,14 @@ vimperator.Commands = function () //{{{ }, { usage: ["ec[ho] {expr}"], - short_help: "Display a string at the bottom of the window", + shortHelp: "Display a string at the bottom of the window", help: "Useful for showing informational messages. Multiple lines can be separated by \\n.
" + "{expr} can either be a quoted string, or any expression which can be fed to eval() like 4+5. " + "You can also view the source code of objects and functions if the return value of {expr} is an object or function.", completer: function (filter) { return vimperator.completion.javascript(filter); } } )); - addDefaultCommand(new vimperator.Command(["echoe[rr]"], + commandManager.add(new vimperator.Command(["echoe[rr]"], function (args) { var res = argToString(args, false); @@ -549,26 +543,26 @@ vimperator.Commands = function () //{{{ }, { usage: ["echoe[rr] {expr}"], - short_help: "Display an error string at the bottom of the window", + shortHelp: "Display an error string at the bottom of the window", help: "Just like :ec[ho], but echoes the result highlighted in red. Useful for showing important messages.", completer: function (filter) { return vimperator.completion.javascript(filter); } } )); - addDefaultCommand(new vimperator.Command(["exe[cute]"], - function (args) { vimperator.execute(args) }, + commandManager.add(new vimperator.Command(["exe[cute]"], + function (args) { vimperator.execute(args); }, { usage: ["exe[cute] {expr1} [ ... ]"], - short_help: "Execute the string that results from the evaluation of {expr1} as an Ex command.", + shortHelp: "Execute the string that results from the evaluation of {expr1} as an Ex command.", help: "Example: :execute echo test shows a message with the text "test".
" } )); - addDefaultCommand(new vimperator.Command(["exu[sage]"], + commandManager.add(new vimperator.Command(["exu[sage]"], function (args, special, count, modifiers) { vimperator.help("commands", special, null, modifiers); }, { - short_help: "Show help for Ex commands" + shortHelp: "Show help for Ex commands" } )); - addDefaultCommand(new vimperator.Command(["fo[rward]", "fw"], + commandManager.add(new vimperator.Command(["fo[rward]", "fw"], function (args, special, count) { if (special) @@ -592,7 +586,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["[count]fo[rward][!] [url]"], - short_help: "Go forward in the browser history", + shortHelp: "Go forward in the browser history", help: "Count is supported, :3forward goes forward 3 pages in the browser history.
" + "The special version :forward! goes to the end of the browser history.", completer: function (filter) @@ -611,18 +605,18 @@ vimperator.Commands = function () //{{{ } } )); - addDefaultCommand(new vimperator.Command(["ha[rdcopy]"], + commandManager.add(new vimperator.Command(["ha[rdcopy]"], function () { getBrowser().contentWindow.print(); }, { - short_help: "Print current document", + shortHelp: "Print current document", help: "Open a GUI dialog where you can select the printer, number of copies, orientation, etc." } )); - addDefaultCommand(new vimperator.Command(["h[elp]"], + commandManager.add(new vimperator.Command(["h[elp]"], function (args, special, count, modifiers) { vimperator.help(args, special, null, modifiers); }, { usage: ["h[elp] {subject}"], - short_help: "Open the help window", + shortHelp: "Open the help window", help: "You can jump to the specified {subject} with :help {subject}.
" + "Make sure you use the full Vim notation when jumping to {subject}. This means:
" + "" + "You can however use partial stings in the tab completion, so :help he<Tab> completes :help :help.", - completer: function (filter) { return vimperator.completion.get_help_completions(filter); } + completer: function (filter) { return vimperator.completion.help(filter); } } )); - addDefaultCommand(new vimperator.Command(["hist[ory]", "hs"], + commandManager.add(new vimperator.Command(["hist[ory]", "hs"], function (args, special) { vimperator.history.list(args, special); }, { usage: ["hist[ory] [filter]", "history!"], - short_help: "Show recently visited URLs", + shortHelp: "Show recently visited URLs", help: "Open the message window at the bottom of the screen with all history items which match [filter] either in the title or URL.
" + "The special version :history! opens the default Firefox history window.", - completer: function (filter) { return vimperator.completion.get_history_completions(filter); } + completer: function (filter) { return vimperator.completion.history(filter); } } )); - addDefaultCommand(new vimperator.Command(["javas[cript]", "js"], + commandManager.add(new vimperator.Command(["javas[cript]", "js"], function (args, special) { if (special) // open javascript console @@ -656,7 +650,8 @@ vimperator.Commands = function () //{{{ if (matches && matches[2]) { vimperator.commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"), - function (code) { + function (code) + { try { eval(matches[1] + "\n" + code); @@ -682,7 +677,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["javas[cript] {cmd}", "javascript <<{endpattern}\\n{script}\\n{endpattern}", "javascript[!]"], // \\n is changed to
in the help.js code - short_help: "Run any JavaScript command through eval()", + shortHelp: "Run any JavaScript command through eval()", help: "Acts as a JavaScript interpreter by passing the argument to eval().
" + ":javascript alert('Hello world') shows a dialog box with the text \"Hello world\".
" + ":javascript <<EOF reads all the lines until a line starting with 'EOF' is found, and interpret them with the JavaScript eval() function.
" + @@ -693,7 +688,7 @@ vimperator.Commands = function () //{{{ completer: function (filter) { return vimperator.completion.javascript(filter); } } )); - addDefaultCommand(new vimperator.Command(["let"], + commandManager.add(new vimperator.Command(["let"], function (args) { if (!args) @@ -733,7 +728,8 @@ vimperator.Commands = function () //{{{ return vimperator.echoerr("E15: Invalid expression: " + match[4]); else { - if (!reference[0]) { + if (!reference[0]) + { if (reference[2] == "g") reference[0] = vimperator.globalVariables; else @@ -773,7 +769,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["let {var-name} [+-.]= {expr1}", "let {var-name}", "let"], - short_help: "Sets or lists a variable", + shortHelp: "Sets or lists a variable", help: "Sets the variable {var-name} " + "to the value of the expression {expr1}." + "If no expression is given, the value of the variable is displayed." + @@ -790,14 +786,14 @@ vimperator.Commands = function () //{{{ var matches = args.match(/^([^\s]+)(?:\s+(.+))?$/); var [lhs, rhs] = [matches[1], matches[2]]; - var leader_reg = //i; + var leaderRegexp = //i; - if (leader_reg.test(lhs)) + if (leaderRegexp.test(lhs)) { - var leader_ref = vimperator.variableReference("mapleader"); - var leader = leader_ref[0] ? leader_ref[0][leader_ref[1]] : "\\"; + var leaderRef = vimperator.variableReference("mapleader"); + var leader = leaderRef[0] ? leaderRef[0][leaderRef[1]] : "\\"; - lhs = lhs.replace(leader_reg, leader); + lhs = lhs.replace(leaderRegexp, leader); } if (rhs) @@ -813,16 +809,16 @@ vimperator.Commands = function () //{{{ vimperator.mappings.list(vimperator.modes.NORMAL, lhs); } } - addDefaultCommand(new vimperator.Command(["map"], - function (args) { map(args, false) }, + commandManager.add(new vimperator.Command(["map"], + function (args) { map(args, false); }, { usage: ["map {lhs} {rhs}", "map {lhs}", "map"], - short_help: "Map the key sequence {lhs} to {rhs}", + shortHelp: "Map the key sequence {lhs} to {rhs}", help: "The {rhs} is remapped, allowing for nested and recursive mappings.
" + "Mappings are NOT saved during sessions, make sure you put them in your vimperatorrc file!" } )); - addDefaultCommand(new vimperator.Command(["mapc[lear]"], + commandManager.add(new vimperator.Command(["mapc[lear]"], function (args) { if (args) @@ -834,12 +830,12 @@ vimperator.Commands = function () //{{{ vimperator.mappings.removeAll(vimperator.modes.NORMAL); }, { - short_help: "Remove all mappings", + shortHelp: "Remove all mappings", help: "All user-defined mappings which were set by " + ":map or :noremap are cleared." } )); - addDefaultCommand(new vimperator.Command(["ma[rk]"], + commandManager.add(new vimperator.Command(["ma[rk]"], function (args) { if (!args) @@ -862,10 +858,10 @@ vimperator.Commands = function () //{{{ }, { usage: ["ma[rk] {a-zA-Z}"], - short_help: "Mark current location within the web page" + shortHelp: "Mark current location within the web page" } )); - addDefaultCommand(new vimperator.Command(["marks"], + commandManager.add(new vimperator.Command(["marks"], function (args) { // ignore invalid mark characters unless there are no valid mark chars @@ -880,11 +876,11 @@ vimperator.Commands = function () //{{{ }, { usage: ["marks [arg]"], - short_help: "Show all location marks of current web page", + shortHelp: "Show all location marks of current web page", help: "If [arg] is specified then limit the list to those marks mentioned." } )); - addDefaultCommand(new vimperator.Command(["mkv[imperatorrc]"], + commandManager.add(new vimperator.Command(["mkv[imperatorrc]"], function (args, special) { var filename; @@ -915,7 +911,7 @@ vimperator.Commands = function () //{{{ { // TODO: options should be queried for this info // TODO: string/list options might need escaping in future - if (!/fullscreen|usermode/.test(option.name) && option.value != option.default_value) + if (!/fullscreen|usermode/.test(option.name) && option.value != option.defaultValue) { if (option.type == "boolean") line += "set " + (option.value ? option.name : "no" + option.name) + "\n"; @@ -930,24 +926,24 @@ vimperator.Commands = function () //{{{ }, { usage: ["mkv[imperatorrc] [file]"], - short_help: "Write current key mappings and changed options to [file]", + shortHelp: "Write current key mappings and changed options to [file]", help: "If no [file] is specified then ~/.vimperatorrc is written unless this file already exists. " + "The special version will overwrite [file] if it exists.
" + "WARNING: this differs from Vim's behavior which defaults to writing the file in the current directory." } )); - addDefaultCommand(new vimperator.Command(["noh[lsearch]"], + commandManager.add(new vimperator.Command(["noh[lsearch]"], function (args) { vimperator.search.clear(); }, { - short_help: "Remove the search highlighting", + shortHelp: "Remove the search highlighting", help: "The document highlighting is turned back on when another search command is used or the " + "'hlsearch' option is set." } )); - addDefaultCommand(new vimperator.Command(["norm[al]"], + commandManager.add(new vimperator.Command(["norm[al]"], function (args, special) { if (!args) @@ -960,21 +956,21 @@ vimperator.Commands = function () //{{{ }, { usage: ["norm[al][!] {commands}"], - short_help: "Execute Normal mode commands", + shortHelp: "Execute Normal mode commands", help: "Example: :normal 20j scrolls 20 lines down. " + "If the [!] is specified mappings will not be used." } )); // TODO: remove duplication in :map - addDefaultCommand(new vimperator.Command(["no[remap]"], - function (args) { map(args, true) }, + commandManager.add(new vimperator.Command(["no[remap]"], + function (args) { map(args, true); }, { usage: ["no[remap] {lhs} {rhs}", "no[remap] {lhs}", "no[remap]"], - short_help: "Map the key sequence {lhs} to {rhs}", + shortHelp: "Map the key sequence {lhs} to {rhs}", help: "No remapping of the {rhs} is performed." } )); - addDefaultCommand(new vimperator.Command(["o[pen]", "e[dit]"], + commandManager.add(new vimperator.Command(["o[pen]", "e[dit]"], function (args, special) { if (args) @@ -991,7 +987,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["o[pen] [url] [, url]"], - short_help: "Open one or more URLs in the current tab", + shortHelp: "Open one or more URLs in the current tab", help: "Multiple URLs can be separated with \", \". Note that the space after the comma is required.
" + "Each token is analyzed and in this order:
" + "
    " + @@ -1014,23 +1010,23 @@ vimperator.Commands = function () //{{{ "The items which are completed on <Tab> are specified in the 'complete' option.
    " + "Without argument, reloads the current page.
    " + "Without argument but with !, reloads the current page skipping the cache.", - completer: function (filter) { return vimperator.completion.get_url_completions(filter); } + completer: function (filter) { return vimperator.completion.url(filter); } } )); - addDefaultCommand(new vimperator.Command(["pa[geinfo]"], + commandManager.add(new vimperator.Command(["pa[geinfo]"], function () { vimperator.buffer.pageInfo(true); }, { - short_help: "Show general and/or meta-content site informations", + shortHelp: "Show general and/or meta-content site informations", help: "Show general and/or meta-content site informations" } )); - addDefaultCommand(new vimperator.Command(["pc[lose]"], + commandManager.add(new vimperator.Command(["pc[lose]"], function () { vimperator.previewwindow.hide(); }, { - short_help: "Close preview window on bottom of screen" + shortHelp: "Close preview window on bottom of screen" } )); - addDefaultCommand(new vimperator.Command(["pref[erences]", "prefs"], + commandManager.add(new vimperator.Command(["pref[erences]", "prefs"], function (args, special, count, modifiers) { if (!args) @@ -1056,13 +1052,13 @@ vimperator.Commands = function () //{{{ }, { usage: ["pref[erences][!]"], - short_help: "Show Browser Preferences", + shortHelp: "Show Browser Preferences", help: "You can change the browser preferences from this dialog. " + "Be aware that not all Firefox preferences work, because Vimperator overrides some key bindings and changes Firefox's GUI.
    " + ":prefs! opens about:config in the current tab where you can change advanced Firefox preferences." } )); - addDefaultCommand(new vimperator.Command(["qma[rk]"], + commandManager.add(new vimperator.Command(["qma[rk]"], function (args) { if (!args) @@ -1081,12 +1077,12 @@ vimperator.Commands = function () //{{{ }, { usage: ["qma[rk] {a-zA-Z0-9} [url]"], - short_help: "Mark a URL with a letter for quick access", + shortHelp: "Mark a URL with a letter for quick access", help: "You can also mark whole groups like this:
    "+ ":qmark f http://forum1.com, http://forum2.com, imdb some artist" } )); - addDefaultCommand(new vimperator.Command(["qmarks"], + commandManager.add(new vimperator.Command(["qmarks"], function (args) { // ignore invalid mark characters unless there are no valid mark chars @@ -1101,57 +1097,57 @@ vimperator.Commands = function () //{{{ }, { usage: ["qmarks [arg]"], - short_help: "Show all QuickMarks", + shortHelp: "Show all QuickMarks", help: "If [arg] is specified then limit the list to those QuickMarks mentioned." } )); - addDefaultCommand(new vimperator.Command(["q[uit]"], + commandManager.add(new vimperator.Command(["q[uit]"], function () { vimperator.tabs.remove(getBrowser().mCurrentTab, 1, false, 1); }, { - short_help: "Quit current tab", + shortHelp: "Quit current tab", help: "If this is the last tab in the window, close the window. If this was the " + "last window, close Vimperator. When quitting Vimperator, the session is not stored." } )); - addDefaultCommand(new vimperator.Command(["quita[ll]", "qa[ll]"], + commandManager.add(new vimperator.Command(["quita[ll]", "qa[ll]"], function () { vimperator.quit(false); }, { - short_help: "Quit Vimperator", + shortHelp: "Quit Vimperator", help: "Quit Vimperator, no matter how many tabs/windows are open. The session is not stored." } )); - addDefaultCommand(new vimperator.Command(["re[load]"], + commandManager.add(new vimperator.Command(["re[load]"], function (args, special) { vimperator.tabs.reload(getBrowser().mCurrentTab, special); }, { usage: ["re[load][!]"], - short_help: "Reload current page", + shortHelp: "Reload current page", help: "Forces reloading of the current page. If ! is given, skip the cache." } )); - addDefaultCommand(new vimperator.Command(["reloada[ll]"], + commandManager.add(new vimperator.Command(["reloada[ll]"], function (args, special) { vimperator.tabs.reloadAll(special); }, { usage: ["reloada[ll][!]"], - short_help: "Reload all pages", + shortHelp: "Reload all pages", help: "Forces reloading of all pages. If ! is given, skip the cache." } )); - addDefaultCommand(new vimperator.Command(["res[tart]"], + commandManager.add(new vimperator.Command(["res[tart]"], function () { vimperator.restart(); }, { - short_help: "Force the browser to restart", + shortHelp: "Force the browser to restart", help: "Useful when installing extensions." } )); - addDefaultCommand(new vimperator.Command(["sav[eas]", "w[rite]"], + commandManager.add(new vimperator.Command(["sav[eas]", "w[rite]"], function () { saveDocument(window.content.document); }, { - short_help: "Save current web page to disk", + shortHelp: "Save current web page to disk", help: "Opens the original Firefox \"Save page as...\" dialog.
    " + "There, you can save the current web page to disk with various options." } )); - addDefaultCommand(new vimperator.Command(["se[t]"], + commandManager.add(new vimperator.Command(["se[t]"], // TODO: support setting multiple options at once function (args, special, count, modifiers) { @@ -1161,11 +1157,11 @@ vimperator.Commands = function () //{{{ return; } - var only_non_default = false; // used for :set to print non-default options + var onlyNondefault = false; // used for :set to print non-default options if (!args) { args = "all"; - only_non_default = true; + onlyNondefault = true; } // 1 2 3 4 5 6 @@ -1176,9 +1172,9 @@ vimperator.Commands = function () //{{{ return; } - var unset_boolean = false; + var unsetBoolean = false; if (matches[1] == "no") - unset_boolean = true; + unsetBoolean = true; var name = matches[2]; var all = false; @@ -1192,19 +1188,19 @@ vimperator.Commands = function () //{{{ return; } - var value_given = !!matches[4]; + var valueGiven = !!matches[4]; var get = false; - if (all || matches[3] == "?" || (option.type != "boolean" && !value_given)) + if (all || matches[3] == "?" || (option.type != "boolean" && !valueGiven)) get = true; var reset = false; if (matches[3] == "&") reset = true; - var invert_boolean = false; + var invertBoolean = false; if (matches[1] == "inv" || matches[3] == "!") - invert_boolean = true; + invertBoolean = true; var operator = matches[5]; @@ -1230,7 +1226,7 @@ vimperator.Commands = function () //{{{ { if (all) { - vimperator.options.list(only_non_default); + vimperator.options.list(onlyNondefault); } else { @@ -1246,22 +1242,22 @@ vimperator.Commands = function () //{{{ // benefit else { - var current_value = option.value; - var new_value; + var currentValue = option.value; + var newValue; switch (option.type) { case "boolean": - if (value_given) + if (valueGiven) { vimperator.echoerr("E474: Invalid argument: " + args); return; } - if (invert_boolean) - new_value = !option.value; + if (invertBoolean) + newValue = !option.value; else - new_value = !unset_boolean; + newValue = !unsetBoolean; break; @@ -1275,64 +1271,64 @@ vimperator.Commands = function () //{{{ } if (operator == "+") - new_value = current_value + value; + newValue = currentValue + value; else if (operator == "-") - new_value = current_value - value; + newValue = currentValue - value; else if (operator == "^") - new_value = current_value * value; + newValue = currentValue * value; else - new_value = value; + newValue = value; break; case "charlist": if (operator == "+") - new_value = current_value.replace(new RegExp("[" + value + "]", "g"), "") + value; + newValue = currentValue.replace(new RegExp("[" + value + "]", "g"), "") + value; else if (operator == "-") - new_value = current_value.replace(value, ""); + newValue = currentValue.replace(value, ""); else if (operator == "^") // NOTE: Vim doesn't prepend if there's a match in the current value - new_value = value + current_value.replace(new RegExp("[" + value + "]", "g"), ""); + newValue = value + currentValue.replace(new RegExp("[" + value + "]", "g"), ""); else - new_value = value; + newValue = value; break; case "stringlist": if (operator == "+") { - if (!current_value.match(value)) - new_value = (current_value ? current_value + "," : "") + value; + if (!currentValue.match(value)) + newValue = (currentValue ? currentValue + "," : "") + value; else - new_value = current_value; + newValue = currentValue; } else if (operator == "-") { - new_value = current_value.replace(new RegExp("^" + value + ",?|," + value), ""); + newValue = currentValue.replace(new RegExp("^" + value + ",?|," + value), ""); } else if (operator == "^") { - if (!current_value.match(value)) - new_value = value + (current_value ? "," : "") + current_value; + if (!currentValue.match(value)) + newValue = value + (currentValue ? "," : "") + currentValue; else - new_value = current_value; + newValue = currentValue; } else { - new_value = value; + newValue = value; } break; case "string": if (operator == "+") - new_value = current_value + value; + newValue = currentValue + value; else if (operator == "-") - new_value = current_value.replace(value, ""); + newValue = currentValue.replace(value, ""); else if (operator == "^") - new_value = value + current_value; + newValue = value + currentValue; else - new_value = value; + newValue = value; break; @@ -1340,8 +1336,8 @@ vimperator.Commands = function () //{{{ vimperator.echoerr("E685: Internal error: option type `" + option.type + "' not supported"); } - if (option.isValidValue(new_value)) - option.value = new_value; + if (option.isValidValue(newValue)) + option.value = newValue; else // FIXME: need to be able to specify more specific errors vimperator.echoerr("E474: Invalid argument: " + args); @@ -1349,7 +1345,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["se[t][!]", "se[t] {option}?", "se[t] [no]{option}", "se[t] {option}[+-]={value}", "se[t] {option}! | inv{option}", "se[t] {option}&"], - short_help: "Set an option", + shortHelp: "Set an option", help: "Permanently change an option.
    " + ":set without an argument shows all Vimperator options which differ from their default values.
    " + ":set! without an argument shows all about:config preferences which differ from their default values.
    " + @@ -1362,11 +1358,11 @@ vimperator.Commands = function () //{{{ ":set option+={value}, :set option^={value} and :set option-={value} " + "adds/multiplies/subtracts {value} from a number option and appends/prepends/removes {value} from a string option.
    " + ":set all shows the current value of all options and :set all& resets all options to their default values.
    ", - completer: function (filter) { return vimperator.completion.get_options_completions(filter); } + completer: function (filter) { return vimperator.completion.option(filter); } } )); // TODO: sclose instead? - addDefaultCommand(new vimperator.Command(["sbcl[ose]"], + commandManager.add(new vimperator.Command(["sbcl[ose]"], function (args) { if (args) @@ -1379,12 +1375,12 @@ vimperator.Commands = function () //{{{ toggleSidebar(); }, { - short_help: "Close the sidebar window" + shortHelp: "Close the sidebar window" } )); // TODO: sopen instead? Separate :sidebar from :sbopen and make them behave // more like :cw, :cope etc - addDefaultCommand(new vimperator.Command(["sideb[ar]", "sb[ar]", "sbope[n]"], + commandManager.add(new vimperator.Command(["sideb[ar]", "sb[ar]", "sbope[n]"], function (args) { if (!args) @@ -1410,14 +1406,14 @@ vimperator.Commands = function () //{{{ }, { usage: ["sidebar {name}"], - short_help: "Open the sidebar window", + shortHelp: "Open the sidebar window", help: "{name} is any of the menu items listed under the standard Firefox View->Sidebar " + "menu. Add-ons, Preferences and Downloads are also available in the sidebar.", - completer: function (filter) { return vimperator.completion.get_sidebar_completions(filter); } + completer: function (filter) { return vimperator.completion.sidebar(filter); } } )); - addDefaultCommand(new vimperator.Command(["so[urce]"], - function (args) + commandManager.add(new vimperator.Command(["so[urce]"], + function (args, special) { // FIXME: implement proper filename quoting //if (/[^\\]\s/.test(args)) @@ -1426,11 +1422,11 @@ vimperator.Commands = function () //{{{ // return; //} - vimperator.source(args); + vimperator.source(args, special); }, { usage: ["so[urce][!] {file}"], - short_help: "Read Ex commands from {file}", + shortHelp: "Read Ex commands from {file}", help: "You can either source files which mostly contain Ex commands like map < gt " + "and put JavaScript code within a:
    " + "js <<EOF
    hello = function () {
      alert(\"Hello world\");
    }
    EOF
    section.
    " + @@ -1440,43 +1436,43 @@ vimperator.Commands = function () //{{{ "The .vimperatorrc file in your home directory and any files in ~/.vimperator/plugin/ are always sourced at startup.
    " + "~ is supported as a shortcut for the $HOME directory.
    " + "If ! is specified, errors are not printed.", - completer: function (filter) { return vimperator.completion.get_file_completions(filter); } + completer: function (filter) { return vimperator.completion.file(filter); } } )); - addDefaultCommand(new vimperator.Command(["st[op]"], + commandManager.add(new vimperator.Command(["st[op]"], BrowserStop, { - short_help: "Stop loading", + shortHelp: "Stop loading", help: "Stop loading current web page." } )); - addDefaultCommand(new vimperator.Command(["tab"], + commandManager.add(new vimperator.Command(["tab"], function (args) { vimperator.execute(args, { inTab: true }); }, { usage: ["tab {cmd}"], - short_help: "Execute {cmd} and tell it to output in a new tab", + shortHelp: "Execute {cmd} and tell it to output in a new tab", help: "Works only for commands that support it, currently:" + "
    • :tab help
    • " + "
    • :tab prefs[!]
    ", - completer: function (filter) { return vimperator.completion.get_command_completions(filter); } + completer: function (filter) { return vimperator.completion.command(filter); } } )); - addDefaultCommand(new vimperator.Command(["tabl[ast]"], + commandManager.add(new vimperator.Command(["tabl[ast]"], function () { vimperator.tabs.select("$", false); }, { - short_help: "Switch to the last tab" + shortHelp: "Switch to the last tab" } )); - addDefaultCommand(new vimperator.Command(["tabm[ove]"], + commandManager.add(new vimperator.Command(["tabm[ove]"], function (args, special) { vimperator.tabs.move(getBrowser().mCurrentTab, args, special); }, { usage: ["tabm[ove] [N]", "tabm[ove][!] +N | -N"], - short_help: "Move the current tab after tab N", + shortHelp: "Move the current tab after tab N", help: "When N is 0 the current tab is made the first one. Without N the current tab is made the last one. " + "N can also be prefixed with '+' or '-' to indicate a relative movement. If ! is specified the movement wraps around the start or end of the tab list." } )); - addDefaultCommand(new vimperator.Command(["tabn[ext]", "tn[ext]"], + commandManager.add(new vimperator.Command(["tabn[ext]", "tn[ext]"], // TODO: count support function (args) { @@ -1487,7 +1483,7 @@ vimperator.Commands = function () //{{{ else if (/^\d+$/.test(args)) { var index = parseInt(args, 10) - 1; - if (index < vimperator.tabs.count()) + if (index < vimperator.tabs.count) vimperator.tabs.select(index, true); else vimperator.beep(); @@ -1499,17 +1495,17 @@ vimperator.Commands = function () //{{{ }, { usage: ["tabn[ext] [count]"], - short_help: "Switch to the next or [count]th tab", + shortHelp: "Switch to the next or [count]th tab", help: "Cycles to the first tab when the last is selected and {count} is not specified." } )); - addDefaultCommand(new vimperator.Command(["tabo[nly]"], + commandManager.add(new vimperator.Command(["tabo[nly]"], function () { vimperator.tabs.keepOnly(getBrowser().mCurrentTab); }, { - short_help: "Close all other tabs" + shortHelp: "Close all other tabs" } )); - addDefaultCommand(new vimperator.Command(["tabopen", "t[open]", "tabnew", "tabe[dit]"], + commandManager.add(new vimperator.Command(["tabopen", "t[open]", "tabnew", "tabe[dit]"], function (args, special) { var where = special ? vimperator.NEW_TAB : vimperator.NEW_BACKGROUND_TAB; @@ -1523,13 +1519,13 @@ vimperator.Commands = function () //{{{ }, { usage: ["tabopen [url] [, url]"], - short_help: "Open one or more URLs in a new tab", + shortHelp: "Open one or more URLs in a new tab", help: "Like :open but open URLs in a new tab.
    " + "If used with !, the 'tabopen' value of the 'activate' option is negated.", - completer: function (filter) { return vimperator.completion.get_url_completions(filter); } + completer: function (filter) { return vimperator.completion.url(filter); } } )); - addDefaultCommand(new vimperator.Command(["tabp[revious]", "tp[revious]", "tabN[ext]", "tN[ext]"], + commandManager.add(new vimperator.Command(["tabp[revious]", "tp[revious]", "tabN[ext]", "tN[ext]"], // TODO: count support function (args) { @@ -1542,18 +1538,18 @@ vimperator.Commands = function () //{{{ }, { usage: ["tabp[revious] [count]"], - short_help: "Switch to the previous tab or go [count] tabs back", + shortHelp: "Switch to the previous tab or go [count] tabs back", help: "Wraps around from the first tab to the last tab." } )); - addDefaultCommand(new vimperator.Command(["tabr[ewind]", "tabfir[st]"], + commandManager.add(new vimperator.Command(["tabr[ewind]", "tabfir[st]"], function () { vimperator.tabs.select(0, false); }, { usage: ["tabr[ewind]", "tabfir[st]"], - short_help: "Switch to the first tab" + shortHelp: "Switch to the first tab" } )); - addDefaultCommand(new vimperator.Command(["time"], + commandManager.add(new vimperator.Command(["time"], function (args, special, count) { try @@ -1561,7 +1557,7 @@ vimperator.Commands = function () //{{{ if (count > 1) { var i = count; - var before_time = Date.now(); + var beforeTime = Date.now(); if (args && args[0] == ":") { @@ -1577,43 +1573,43 @@ vimperator.Commands = function () //{{{ if (special) return; - var after_time = Date.now(); + var afterTime = Date.now(); - if ((after_time - before_time) / count >= 100) + if ((afterTime - beforeTime) / count >= 100) { - var each = ((after_time - before_time) / 1000.0 / count); - var each_units = "sec"; + var each = ((afterTime - beforeTime) / 1000.0 / count); + var eachUnits = "sec"; } else { - var each = ((after_time - before_time) / count); - var each_units = "msec"; + var each = ((afterTime - beforeTime) / count); + var eachUnits = "msec"; } - if (after_time - before_time >= 100) + if (afterTime - beforeTime >= 100) { - var total = ((after_time - before_time) / 1000.0); - var total_units = "sec"; + var total = ((afterTime - beforeTime) / 1000.0); + var totalUnits = "sec"; } else { - var total = (after_time - before_time); - var total_units = "msec"; + var total = (afterTime - beforeTime); + var totalUnits = "msec"; } var str = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
    " + "" + "" + "" + - "" + - "" + + "" + + "" + "
    Code execution summary
    Executed:" + count + "times
    Each time:" + each.toFixed(2) + "" + each_units + "
    Total time:" + total.toFixed(2) + "" + total_units + "
    Each time:" + each.toFixed(2) + "" + eachUnits + "
    Total time:" + total.toFixed(2) + "" + totalUnits + "
    "; vimperator.commandline.echo(str, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); } else { - var before_time = Date.now(); + var beforeTime = Date.now(); if (args && args[0] == ":") vimperator.execute(args); else @@ -1622,12 +1618,12 @@ vimperator.Commands = function () //{{{ if (special) return; - var after_time = Date.now(); + var afterTime = Date.now(); - if (after_time - before_time >= 100) - vimperator.echo("Total time: " + ((after_time - before_time) / 1000.0).toFixed(2) + " sec"); + if (afterTime - beforeTime >= 100) + vimperator.echo("Total time: " + ((afterTime - beforeTime) / 1000.0).toFixed(2) + " sec"); else - vimperator.echo("Total time: " + (after_time - before_time) + " msec"); + vimperator.echo("Total time: " + (afterTime - beforeTime) + " msec"); } } catch (e) @@ -1637,14 +1633,14 @@ vimperator.Commands = function () //{{{ }, { usage: ["{count}time[!] {code|:command}"], - short_help: "Profile a piece of code or a command", + shortHelp: "Profile a piece of code or a command", help: "Runs {code} {count} times (default 1) and returns the elapsed time. " + "{code} is always passed to JavaScript's eval(), which might be slow, so take the results with a grain of salt.
    " + "If {code} starts with a :, it is executed as a Vimperator command.
    " + "Use the special version with [!] if you just want to run any command multiple times without showing profiling statistics." } )); - addDefaultCommand(new vimperator.Command(["u[ndo]"], + commandManager.add(new vimperator.Command(["u[ndo]"], function (args, special, count) { if (count < 1) @@ -1667,7 +1663,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["[count]u[ndo][!] [url]"], - short_help: "Undo closing of a tab", + shortHelp: "Undo closing of a tab", help: "If a count is given, don't close the last but the [count]th last tab. " + "With [url] restores the tab matching the url.", completer: function (filter) @@ -1688,7 +1684,7 @@ vimperator.Commands = function () //{{{ } } )); - addDefaultCommand(new vimperator.Command(["undoa[ll]"], + commandManager.add(new vimperator.Command(["undoa[ll]"], function (args, special, count) { if (count > -1) @@ -1708,11 +1704,11 @@ vimperator.Commands = function () //{{{ undoCloseTab(); // doesn't work with i as the index to undoCloseTab }, { - short_help: "Undo closing of all closed tabs", + shortHelp: "Undo closing of all closed tabs", help: "Firefox stores up to 10 closed tabs, even after a browser restart." } )); - addDefaultCommand(new vimperator.Command(["unl[et]"], + commandManager.add(new vimperator.Command(["unl[et]"], function (args, special) { if (!args) @@ -1736,12 +1732,12 @@ vimperator.Commands = function () //{{{ }, { usage: ["unl[et][!] {name} ..."], - short_help: "Deletes a variable.", + shortHelp: "Deletes a variable.", help: "Deletes the variable {name}." + "Several variable names can be given." } )); - addDefaultCommand(new vimperator.Command(["unm[ap]"], + commandManager.add(new vimperator.Command(["unm[ap]"], function (args) { if (!args) @@ -1759,11 +1755,11 @@ vimperator.Commands = function () //{{{ }, { usage: ["unm[ap] {lhs}"], - short_help: "Remove the mapping of {lhs}", + shortHelp: "Remove the mapping of {lhs}", help: "" } )); - addDefaultCommand(new vimperator.Command(["ve[rsion]"], + commandManager.add(new vimperator.Command(["ve[rsion]"], function (args, special) { if (special) @@ -1774,27 +1770,27 @@ vimperator.Commands = function () //{{{ }, { usage: ["ve[rsion][!]"], - short_help: "Show version information", + shortHelp: "Show version information", help: "You can show the Firefox version page with :version!." } )); - addDefaultCommand(new vimperator.Command(["viu[sage]"], + commandManager.add(new vimperator.Command(["viu[sage]"], function (args, special, count, modifiers) { vimperator.help("mappings", special, null, modifiers); }, { - short_help: "Show help for normal mode commands" + shortHelp: "Show help for normal mode commands" } )); - addDefaultCommand(new vimperator.Command(["winc[lose]", "wc[lose]"], + commandManager.add(new vimperator.Command(["winc[lose]", "wc[lose]"], function (args) { window.close(); }, { usage: ["winc[ose] [url] [, url]"], - short_help: "Close window" + shortHelp: "Close window" } )); - addDefaultCommand(new vimperator.Command(["wino[pen]", "wo[pen]", "wine[dit]"], + commandManager.add(new vimperator.Command(["wino[pen]", "wo[pen]", "wine[dit]"], function (args) { if (args) @@ -1804,20 +1800,20 @@ vimperator.Commands = function () //{{{ }, { usage: ["wino[pen] [url] [, url]"], - short_help: "Open one or more URLs in a new window", + shortHelp: "Open one or more URLs in a new window", help: "Like :open but open URLs in a new window.
    " } )); - addDefaultCommand(new vimperator.Command(["wqa[ll]", "wq", "xa[ll]"], + commandManager.add(new vimperator.Command(["wqa[ll]", "wq", "xa[ll]"], function () { vimperator.quit(true); }, { usage: ["wqa[ll]", "xa[ll]"], - short_help: "Save the session and quit", + shortHelp: "Save the session and quit", help: "Quit Vimperator, no matter how many tabs/windows are open. The session is stored.
    " + ":wq is different as in Vim, as it closes the window instead of just one tab by popular demand. Complain on the mailing list, if you want to change that." } )); - addDefaultCommand(new vimperator.Command(["zo[om]"], + commandManager.add(new vimperator.Command(["zo[om]"], function (args) { var level; @@ -1850,19 +1846,19 @@ vimperator.Commands = function () //{{{ }, { usage: ["zo[om] [value]", "zo[om] +{value} | -{value}"], - short_help: "Set zoom value of the web page", + shortHelp: "Set zoom value of the web page", help: "If {value} can be an absolute value between 1 and 2000% or a relative value if prefixed with - or +. " + "If {value} is omitted, zoom is reset to 100%." }, { usage: ["zo[om][!] [value]", "zo[om][!] +{value} | -{value}"], - short_help: "Set zoom value of current web page", + shortHelp: "Set zoom value of current web page", help: "If {value} can be an absolute value between 1 and 2000% or a relative value if prefixed with - or +. " + "If {value} is omitted, zoom is reset to 100%.
    " + "Normally this command operates on the text zoom, if used with [!] it operates on full zoom." } )); - addDefaultCommand(new vimperator.Command(["!", "run"], + commandManager.add(new vimperator.Command(["!", "run"], function (args, special) { // :!! needs to be treated specially as the command parser sets the special flag but removes the ! from args @@ -1870,8 +1866,8 @@ vimperator.Commands = function () //{{{ args = "!" + (args || ""); // TODO: better escaping of ! to also substitute \\! correctly - args = args.replace(/(^|[^\\])!/g, "$1" + last_run_command); - last_run_command = args; + args = args.replace(/(^|[^\\])!/g, "$1" + lastRunCommand); + lastRunCommand = args; var output = vimperator.system(args); if (output) @@ -1879,7 +1875,7 @@ vimperator.Commands = function () //{{{ }, { usage: ["!{cmd}"], - short_help: "Run a command", + shortHelp: "Run a command", help: "Runs {cmd} through system() and displays its output. " + "Any '!' in {cmd} is replaced with the previous external command. " + "But not when there is a backslash before the '!', then that backslash is removed.
    " + @@ -1887,6 +1883,8 @@ vimperator.Commands = function () //{{{ } )); //}}} -} //}}} + + return commandManager; +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/completion.js b/content/completion.js index 7e49f4fd..d5b34c78 100644 --- a/content/completion.js +++ b/content/completion.js @@ -26,14 +26,18 @@ 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.Completion = function () // {{{ +vimperator.Completion = function () //{{{ { - // The completion substrings, used for showing the longest common match - var g_substrings = []; + //////////////////////////////////////////////////////////////////////////////// + ////////////////////// PRIVATE SECTION ///////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + // the completion substrings, used for showing the longest common match + var substrings = []; // function uses smartcase // list = [ [['com1', 'com2'], 'text'], [['com3', 'com4'], 'text'] ] - function build_longest_common_substring(list, filter) //{{{ + function buildLongestCommonSubstring(list, filter) { var filtered = []; var ignorecase = false; @@ -51,19 +55,19 @@ vimperator.Completion = function () // {{{ if (item.indexOf(filter) == -1) continue; - if (g_substrings.length == 0) + if (substrings.length == 0) { - var last_index = item.lastIndexOf(filter); + var lastIndex = item.lastIndexOf(filter); var length = item.length; - for (var k = item.indexOf(filter); k != -1 && k <= last_index; k = item.indexOf(filter, k + 1)) + for (var k = item.indexOf(filter); k != -1 && k <= lastIndex; k = item.indexOf(filter, k + 1)) { for (var l = k + filter.length; l <= length; l++) - g_substrings.push(list[i][0][j].substring(k, l)); + substrings.push(list[i][0][j].substring(k, l)); } } else { - g_substrings = g_substrings.filter(function ($_) { + substrings = substrings.filter(function ($_) { return list[i][0][j].indexOf($_) >= 0; }); } @@ -72,10 +76,10 @@ vimperator.Completion = function () // {{{ } } return filtered; - } //}}} + } - /* this function is case sensitive and should be documented about input and output ;) */ - function build_longest_starting_substring(list, filter) //{{{ + // this function is case sensitive and should be documented about input and output ;) + function buildLongestStartingSubstring(list, filter) { var filtered = []; for (var i = 0; i < list.length; i++) @@ -85,15 +89,15 @@ vimperator.Completion = function () // {{{ if (list[i][0][j].indexOf(filter) != 0) continue; - if (g_substrings.length == 0) + if (substrings.length == 0) { var length = list[i][0][j].length; for (var k = filter.length; k <= length; k++) - g_substrings.push(list[i][0][j].substring(0, k)); + substrings.push(list[i][0][j].substring(0, k)); } else { - g_substrings = g_substrings.filter(function ($_) { + substrings = substrings.filter(function ($_) { return list[i][0][j].indexOf($_) == 0; }); } @@ -102,18 +106,18 @@ vimperator.Completion = function () // {{{ } } return filtered; - } //}}} + } /* discard all entries in the 'urls' array, which don't match 'filter */ - function filter_url_array(urls, filter) //{{{ + function filterUrlArray(urls, filter) { var filtered = []; // completions which don't match the url but just the description // list them add the end of the array - var additional_completions = []; + var additionalCompletions = []; if (!filter) return urls.map(function ($_) { - return [$_[0], $_[1]] + return [$_[0], $_[1]]; }); var ignorecase = false; @@ -122,7 +126,7 @@ vimperator.Completion = function () // {{{ /* * Longest Common Subsequence - * This shouldn't use build_longest_common_substring + * This shouldn't use buildLongestCommonSubstring * for performance reasons, so as not to cycle through the urls twice */ for (var i = 0; i < urls.length; i++) @@ -138,49 +142,54 @@ vimperator.Completion = function () // {{{ if (url.indexOf(filter) == -1) { if (title.indexOf(filter) != -1) - additional_completions.push([ urls[i][0], urls[i][1] ]); + additionalCompletions.push([ urls[i][0], urls[i][1] ]); continue; } - if (g_substrings.length == 0) // Build the substrings + if (substrings.length == 0) // Build the substrings { - var last_index = url.lastIndexOf(filter); - var url_length = url.length; - for (var k = url.indexOf(filter); k != -1 && k <= last_index; k = url.indexOf(filter, k + 1)) + var lastIndex = url.lastIndexOf(filter); + var urlLength = url.length; + for (var k = url.indexOf(filter); k != -1 && k <= lastIndex; k = url.indexOf(filter, k + 1)) { - for (var l = k + filter.length; l <= url_length; l++) - g_substrings.push(url.substring(k, l)); + for (var l = k + filter.length; l <= urlLength; l++) + substrings.push(url.substring(k, l)); } } else { - g_substrings = g_substrings.filter(function ($_) { + substrings = substrings.filter(function ($_) { return url.indexOf($_) >= 0; }); } filtered.push([urls[i][0], urls[i][1]]); } - return filtered.concat(additional_completions); - } //}}} + return filtered.concat(additionalCompletions); + } + + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// PUBLIC SECTION ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ return { + /* * returns the longest common substring * used for the 'longest' setting for wildmode */ - get_longest_substring: function () //{{{ + getLongestSubstring: function () { - if (g_substrings.length == 0) + if (substrings.length == 0) return ""; - var longest = g_substrings[0]; - for (var i = 1; i < g_substrings.length; i++) + var longest = substrings[0]; + for (var i = 1; i < substrings.length; i++) { - if (g_substrings[i].length > longest.length) - longest = g_substrings[i]; + if (substrings[i].length > longest.length) + longest = substrings[i]; } return longest; - }, //}}} + }, /* * filter a list of urls @@ -189,29 +198,29 @@ vimperator.Completion = function () // {{{ * depending on the 'complete' option * if the 'complete' argument is passed like "h", it temporarily overrides the complete option */ - get_url_completions: function (filter, complete) //{{{ + url: function (filter, complete) { var completions = []; - g_substrings = []; + substrings = []; var cpt = complete || vimperator.options["complete"]; // join all completion arrays together for (var i = 0; i < cpt.length; i++) { if (cpt[i] == "s") - completions = completions.concat(this.get_search_completions(filter)); + completions = completions.concat(this.search(filter)); else if (cpt[i] == "b") - completions = completions.concat(this.get_bookmark_completions(filter)); + completions = completions.concat(this.bookmark(filter)); else if (cpt[i] == "h") - completions = completions.concat(this.get_history_completions(filter)); + completions = completions.concat(this.history(filter)); else if (cpt[i] == "f") - completions = completions.concat(this.get_file_completions(filter, true)); + completions = completions.concat(this.file(filter, true)); } return completions; - }, //}}} + }, - get_search_completions: function (filter) //{{{ + search: function (filter) { var engines = vimperator.bookmarks.getSearchEngines().concat(vimperator.bookmarks.getKeywords()); @@ -221,28 +230,28 @@ vimperator.Completion = function () // {{{ var mapped = engines.map(function (engine) { return [[engine[0]], engine[1]]; }); - return build_longest_common_substring(mapped, filter); - }, //}}} + return buildLongestCommonSubstring(mapped, filter); + }, - get_history_completions: function (filter) //{{{ + history: function (filter) { var items = vimperator.history.get(); - return filter_url_array(items, filter); - }, //}}} + return filterUrlArray(items, filter); + }, - get_bookmark_completions: function (filter) //{{{ + bookmark: function (filter) { var bookmarks = vimperator.bookmarks.get(); - return filter_url_array(bookmarks, filter); - }, //}}} + return filterUrlArray(bookmarks, filter); + }, // TODO: support file:// and \ or / path separators on both platforms - get_file_completions: function (filter) + file: function (filter) { // this is now also used as part of the url completion, so the // substrings shouldn't be cleared for that case if (!arguments[1]) - g_substrings = []; + substrings = []; var matches = filter.match(/^(.*[\/\\])(.*?)$/); var dir; @@ -266,56 +275,56 @@ vimperator.Completion = function () // {{{ } - return build_longest_starting_substring(mapped, filter); + return buildLongestStartingSubstring(mapped, filter); }, - get_help_completions: function (filter) //{{{ + help: function (filter) { - var help_array = [[["introduction"], "Introductory text"], - [["initialization"], "Initialization and startup"], - [["mappings"], "Normal mode commands"], - [["commands"], "Ex commands"], - [["options"], "Configuration options"]]; // TODO: hardcoded until we have proper 'pages' - g_substrings = []; + var helpArray = [[["introduction"], "Introductory text"], + [["initialization"], "Initialization and startup"], + [["mappings"], "Normal mode commands"], + [["commands"], "Ex commands"], + [["options"], "Configuration options"]]; // TODO: hardcoded until we have proper 'pages' + substrings = []; for (var command in vimperator.commands) - help_array.push([command.long_names.map(function ($_) { return ":" + $_; }), command.short_help]); - options = this.get_options_completions(filter, true); - help_array = help_array.concat(options.map(function ($_) { + helpArray.push([command.longNames.map(function ($_) { return ":" + $_; }), command.shortHelp]); + options = this.option(filter, true); + helpArray = helpArray.concat(options.map(function ($_) { return [ $_[0].map(function ($_) { return "'" + $_ + "'"; }), $_[1] ]; })); for (var map in vimperator.mappings) - help_array.push([map.names, map.short_help]); + helpArray.push([map.names, map.shortHelp]); - if (!filter) return help_array.map(function ($_) { + if (!filter) return helpArray.map(function ($_) { return [$_[0][0], $_[1]]; // unfiltered, use the first command }); - return build_longest_common_substring(help_array, filter); - }, //}}} + return buildLongestCommonSubstring(helpArray, filter); + }, - get_command_completions: function (filter) //{{{ + command: function (filter) { - g_substrings = []; + substrings = []; var completions = []; if (!filter) { for (var command in vimperator.commands) - completions.push([command.name, command.short_help]); + completions.push([command.name, command.shortHelp]); return completions; } for (var command in vimperator.commands) - completions.push([command.long_names, command.short_help]); - return build_longest_starting_substring(completions, filter); - }, //}}} + completions.push([command.longNames, command.shortHelp]); + return buildLongestStartingSubstring(completions, filter); + }, - get_options_completions: function (filter, unfiltered) //{{{ + option: function (filter, unfiltered) { - g_substrings = []; - var options_completions = []; + substrings = []; + var optionsCompletions = []; var prefix = filter.match(/^no|inv/) || ""; if (prefix) @@ -328,7 +337,7 @@ vimperator.Completion = function () // {{{ { if (prefix && option.type != "boolean") continue; - options.push([option.names, option.short_help]); + options.push([option.names, option.shortHelp]); } return options; } @@ -340,7 +349,7 @@ vimperator.Completion = function () // {{{ { if (prefix && option.type != "boolean") continue; - options.push([prefix + option.name, option.short_help]); + options.push([prefix + option.name, option.shortHelp]); } return options; } @@ -352,15 +361,15 @@ vimperator.Completion = function () // {{{ { if (option.hasName(filter)) { - options_completions.push([filter + "=" + option.value, ""]); - return options_completions; + optionsCompletions.push([filter + "=" + option.value, ""]); + return optionsCompletions; } } - return options_completions; + return optionsCompletions; } // can't use b_l_s_s, since this has special requirements (the prefix) - var filter_length = filter.length; + var filterLength = filter.length; for (var option in vimperator.options) { if (prefix && option.type != "boolean") @@ -371,29 +380,29 @@ vimperator.Completion = function () // {{{ if (option.names[j].indexOf(filter) != 0) continue; - if (g_substrings.length == 0) + if (substrings.length == 0) { var length = option.names[j].length; - for (var k = filter_length; k <= length; k++) - g_substrings.push(prefix + option.names[j].substring(0, k)); + for (var k = filterLength; k <= length; k++) + substrings.push(prefix + option.names[j].substring(0, k)); } else { - g_substrings = g_substrings.filter(function ($_) { + substrings = substrings.filter(function ($_) { return option.names[j].indexOf($_) == 0; }); } - options_completions.push([prefix + option.names[j], option.short_help]); + optionsCompletions.push([prefix + option.names[j], option.shortHelp]); break; } } - return options_completions; - }, //}}} + return optionsCompletions; + }, - get_buffer_completions: function (filter) //{{{ + buffer: function (filter) { - g_substrings = []; + substrings = []; var items = []; var num = getBrowser().browsers.length; var title, url; @@ -424,13 +433,13 @@ vimperator.Completion = function () // {{{ if (!filter) return items.map(function ($_) { return [$_[0][0], $_[1]]; }); - return build_longest_common_substring(items, filter); - }, //}}} + return buildLongestCommonSubstring(items, filter); + }, - get_sidebar_completions: function (filter) //{{{ + sidebar: function (filter) { - g_substrings = []; - var menu = document.getElementById("viewSidebarMenu") + substrings = []; + var menu = document.getElementById("viewSidebarMenu"); var nodes = []; for (var i = 0; i < menu.childNodes.length; i++) @@ -443,12 +452,12 @@ vimperator.Completion = function () // {{{ return [[node[0]], node[1]]; }); - return build_longest_common_substring(mapped, filter); - }, //}}} + return buildLongestCommonSubstring(mapped, filter); + }, javascript: function (str) // {{{ { - g_substrings = []; + substrings = []; var matches = str.match(/^(.*?)(\s*\.\s*)?(\w*)$/); var object = "window"; var filter = matches[3] || ""; @@ -514,18 +523,18 @@ vimperator.Completion = function () // {{{ completions = []; } - return build_longest_starting_substring(completions, filter); + return buildLongestStartingSubstring(completions, filter); }, // }}} // helper function which checks if the given arguments pass "filter" // items must be an array of strings - // if case_sensitive == true, be sure to pass filter already in lowercased version - match: function (filter, items, case_sensitive) + // if caseSensitive == true, be sure to pass filter already in lowercased version + match: function (filter, items, caseSensitive) { - if (typeof(filter) != "string" || !items) + if (typeof filter != "string" || !items) return false; - if (case_sensitive) + if (caseSensitive) { for (var i = 0; i < items.length; i++) { @@ -544,7 +553,7 @@ vimperator.Completion = function () // {{{ return false; }, - exTabCompletion: function (str) //{{{ + exTabCompletion: function (str) { var [count, cmd, special, args] = vimperator.commands.parseCommand(str); var completions = []; @@ -555,7 +564,7 @@ vimperator.Completion = function () // {{{ var matches = str.match(/^(:*\d*)\w*$/); if (matches) { - completions = this.get_command_completions(cmd); + completions = this.command(cmd); start = matches[1].length; } else // dynamically get completions as specified with the command's completer function @@ -587,9 +596,10 @@ vimperator.Completion = function () // {{{ } } return [start, completions]; - } //}}} + } - } -} // }}} + }; + //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/events.js b/content/events.js index bf1a7d3c..7519c9e4 100644 --- a/content/events.js +++ b/content/events.js @@ -74,7 +74,7 @@ vimperator.Events = function () //{{{ ///////////////////////////////////////////////////////// // track if a popup is open or the menubar is active - var active_menubar = false; + var activeMenubar = false; function enterPopupMode(event) { if (event.originalTarget.localName == "tooltip" || event.originalTarget.id == "vimperator-visualbell") @@ -85,17 +85,17 @@ vimperator.Events = function () //{{{ function exitPopupMode() { // gContextMenu is set to NULL by firefox, when a context menu is closed - if (!gContextMenu && !active_menubar) + if (!gContextMenu && !activeMenubar) vimperator.removeMode(null, vimperator.modes.MENU); } function enterMenuMode() { - active_menubar = true; - vimperator.addMode(null, vimperator.modes.MENU) + activeMenubar = true; + vimperator.addMode(null, vimperator.modes.MENU); } function exitMenuMode() { - active_menubar = false; + activeMenubar = false; vimperator.removeMode(null, vimperator.modes.MENU); } window.addEventListener("popupshown", enterPopupMode, true); @@ -182,7 +182,7 @@ vimperator.Events = function () //{{{ var tagname = elt.localName.toLowerCase(); var type = elt.type.toLowerCase(); - if ( (tagname == "input" && (type != "image")) || + if ((tagname == "input" && (type != "image")) || tagname == "textarea" || // tagName == "SELECT" || // tagName == "BUTTON" || @@ -234,571 +234,579 @@ vimperator.Events = function () //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - this.destroy = function () - { - // removeEventListeners() to avoid mem leaks - window.dump("TODO: remove all eventlisteners\n"); + var eventManager = { - getBrowser().removeProgressListener(this.progressListener); - - window.removeEventListener("popupshown", enterPopupMode, true); - window.removeEventListener("popuphidden", exitPopupMode, true); - window.removeEventListener("DOMMenuBarActive", enterMenuMode, true); - window.removeEventListener("DOMMenuBarInactive", exitMenuMode, true); - - window.removeEventListener("keypress", this.onKeyPress, true); - window.removeEventListener("keydown", this.onKeyDown, true); - } - - // This method pushes keys into the event queue from vimperator - // it is similar to vim's feedkeys() method, but cannot cope with - // 2 partially feeded strings, you have to feed one parsable string - // - // @param keys: a string like "2" to pass - // if you want < to be taken literally, prepend it with a \\ - this.feedkeys = function (keys, noremap) - { - var doc = window.document; - var view = window.document.defaultView; - var escapeKey = false; // \ to escape some special keys - - noremap = !!noremap; - - for (var i = 0; i < keys.length; i++) + destroy: function () { - var charCode = keys.charCodeAt(i); - var keyCode = 0; - var shift = false, ctrl = false, alt = false, meta = false; - //if (charCode == 92) // the '\' key FIXME: support the escape key - if (charCode == 60 && !escapeKey) // the '<' key starts a complex key - { - var matches = keys.substr(i + 1).match(/([CSMAcsma]-)*([^>]+)/); - if (matches && matches[2]) - { - if (matches[1]) // check for modifiers - { - ctrl = /[cC]-/.test(matches[1]); - alt = /[aA]-/.test(matches[1]); - shift = /[sS]-/.test(matches[1]); - meta = /[mM]-/.test(matches[1]); - } - if (matches[2].length == 1) - { - if (!ctrl && !alt && !shift && !meta) - return; // an invalid key like - charCode = matches[2].charCodeAt(0); - } - else if (matches[2].toLowerCase() == "space") - { - charCode = 32; - } - else if (keyCode = getKeyCode(matches[2])) - { - charCode = 0; - } - else //an invalid key like was found, stop propagation here (like Vim) - { - return; - } + // removeEventListeners() to avoid mem leaks + window.dump("TODO: remove all eventlisteners\n"); - i += matches[0].length + 1; + getBrowser().removeProgressListener(this.progressListener); + + window.removeEventListener("popupshown", enterPopupMode, true); + window.removeEventListener("popuphidden", exitPopupMode, true); + window.removeEventListener("DOMMenuBarActive", enterMenuMode, true); + window.removeEventListener("DOMMenuBarInactive", exitMenuMode, true); + + window.removeEventListener("keypress", this.onKeyPress, true); + window.removeEventListener("keydown", this.onKeyDown, true); + }, + + // This method pushes keys into the event queue from vimperator + // it is similar to vim's feedkeys() method, but cannot cope with + // 2 partially feeded strings, you have to feed one parsable string + // + // @param keys: a string like "2" to pass + // if you want < to be taken literally, prepend it with a \\ + feedkeys: function (keys, noremap) + { + var doc = window.document; + var view = window.document.defaultView; + var escapeKey = false; // \ to escape some special keys + + noremap = !!noremap; + + for (var i = 0; i < keys.length; i++) + { + var charCode = keys.charCodeAt(i); + var keyCode = 0; + var shift = false, ctrl = false, alt = false, meta = false; + //if (charCode == 92) // the '\' key FIXME: support the escape key + if (charCode == 60 && !escapeKey) // the '<' key starts a complex key + { + var matches = keys.substr(i + 1).match(/([CSMAcsma]-)*([^>]+)/); + if (matches && matches[2]) + { + if (matches[1]) // check for modifiers + { + ctrl = /[cC]-/.test(matches[1]); + alt = /[aA]-/.test(matches[1]); + shift = /[sS]-/.test(matches[1]); + meta = /[mM]-/.test(matches[1]); + } + if (matches[2].length == 1) + { + if (!ctrl && !alt && !shift && !meta) + return; // an invalid key like + charCode = matches[2].charCodeAt(0); + } + else if (matches[2].toLowerCase() == "space") + { + charCode = 32; + } + else if (keyCode = getKeyCode(matches[2])) + { + charCode = 0; + } + else //an invalid key like was found, stop propagation here (like Vim) + { + return; + } + + i += matches[0].length + 1; + } + } + + var elem = window.document.commandDispatcher.focusedElement; + if (!elem) + elem = window.content; + + var evt = doc.createEvent("KeyEvents"); + evt.initKeyEvent("keypress", true, true, view, ctrl, alt, shift, meta, keyCode, charCode); + evt.noremap = noremap; + elem.dispatchEvent(evt); + } + }, + + // this function converts the given event to + // a keycode which can be used in mappings + // e.g. pressing ctrl+n would result in the string "" + // null if unknown key + toString: function (event) + { + if (!event) + return; + + var key = null; + var modifier = ""; + + if (event.ctrlKey) + modifier += "C-"; + if (event.altKey) + modifier += "A-"; + if (event.metaKey) + modifier += "M-"; + + if (event.type == "keypress") + { + if (event.charCode == 0) + { + if (event.shiftKey) + modifier += "S-"; + + for (var i in keyTable) + { + if (keyTable[i][0] == event.keyCode) + { + key = keyTable[i][1][0]; + break; + } + } + } + // special handling of the Space key + else if (event.charCode == 32) + { + if (event.shiftKey) + modifier += "S-"; + key = "Space"; + } + // a normal key like a, b, c, 0, etc. + else if (event.charCode > 0) + { + key = String.fromCharCode(event.charCode); + if (modifier.length == 0) + return key; } } - - var elem = window.document.commandDispatcher.focusedElement; - if (!elem) - elem = window.content; - - var evt = doc.createEvent("KeyEvents"); - evt.initKeyEvent("keypress", true, true, view, ctrl, alt, shift, meta, keyCode, charCode); - evt.noremap = noremap; - elem.dispatchEvent(evt); - } - } - - // this function converts the given event to - // a keycode which can be used in mappings - // e.g. pressing ctrl+n would result in the string "" - // null if unknown key - this.toString = function (event) //{{{ - { - if (!event) - return; - - var key = null; - var modifier = ""; - - if (event.ctrlKey) - modifier += "C-"; - if (event.altKey) - modifier += "A-"; - if (event.metaKey) - modifier += "M-"; - - if (event.type == "keypress") - { - if (event.charCode == 0) + else if (event.type == "click" || event.type == "dblclick") { if (event.shiftKey) modifier += "S-"; + if (event.type == "dblclick") + modifier += "2-"; + // TODO: triple and quadruple click - for (var i in keyTable) + switch (event.button) { - if (keyTable[i][0] == event.keyCode) - { - key = keyTable[i][1][0]; + case 0: + key = "LeftMouse"; + break; + case 1: + key = "MiddleMouse"; + break; + case 2: + key = "RightMouse"; break; - } } } - // special handling of the Space key - else if (event.charCode == 32) - { - if (event.shiftKey) - modifier += "S-"; - key = "Space"; - } - // a normal key like a, b, c, 0, etc. - else if (event.charCode > 0) - { - key = String.fromCharCode(event.charCode); - if (modifier.length == 0) - return key; - } - } - else if (event.type == "click" || event.type == "dblclick") + + if (key == null) + return null; + + // a key like F1 is always enclosed in < and > + return "<" + modifier + key + ">"; + + }, + + isAcceptKey: function (key) { - if (event.shiftKey) - modifier += "S-"; - if (event.type == "dblclick") - modifier += "2-"; - // TODO: triple and quadruple click + return (key == "" || key == "" || key == ""); + }, - switch (event.button) - { - case 0: - key = "LeftMouse"; - break; - case 1: - key = "MiddleMouse"; - break; - case 2: - key = "RightMouse"; - break; - } - } - - if (key == null) - return null; - - // a key like F1 is always enclosed in < and > - return "<" + modifier + key + ">"; - - } //}}} - - this.isAcceptKey = function (key) - { - return (key == "" || key == "" || key == ""); - } - this.isCancelKey = function (key) - { - return (key == "" || key == "" || key == ""); - } - - // global escape handler, is called in ALL modes - this.onEscape = function () - { - if (!vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY)) + isCancelKey: function (key) { + return (key == "" || key == "" || key == ""); + }, + + // global escape handler, is called in ALL modes + onEscape: function () + { + if (!vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY)) + { + if (vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS)) + { + vimperator.removeMode(null, vimperator.modes.ESCAPE_ALL_KEYS); + return; + } + + vimperator.setMode(vimperator.modes.NORMAL); + vimperator.commandline.clear(); + vimperator.hints.disableHahMode(); + vimperator.statusline.updateUrl(); + vimperator.focusContent(); + } + }, + + // this keypress handler gets always called first, even if e.g. + // the commandline has focus + onKeyPress: function (event) + { + var key = vimperator.events.toString(event); + if (!key) + return true; + + var stop = true; // set to false if we should NOT consume this event but let also firefox handle it + + var win = document.commandDispatcher.focusedWindow; + if (win && win.document.designMode == "on") + return true; + + // menus have their own command handlers + if (vimperator.hasMode(vimperator.modes.MENU)) + return true; + + // XXX: for now only, later: input mappings if form element focused + if (isFormElemFocused()) + { + if (key == "") + { + var elt = window.document.commandDispatcher.focusedElement; + + if (elt.setSelectionRange && readFromClipboard()) + // readFromClipboard would return 'undefined' if not checked + // dunno about .setSelectionRange + { + var rangeStart = elt.selectionStart; // caret position + var rangeEnd = elt.selectionEnd; + var tempStr1 = elt.value.substring(0,rangeStart); + var tempStr2 = readFromClipboard(); + var tempStr3 = elt.value.substring(rangeEnd); + elt.value = tempStr1 + tempStr2 + tempStr3; + elt.selectionStart = rangeStart + tempStr2.length; + elt.selectionEnd = elt.selectionStart; + event.preventDefault(); + // prevents additional firefox-clipboard pasting + } + } + return false; + } + + // handle Escape-one-key mode (Ctrl-v) + if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY) && !vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS)) + { + vimperator.removeMode(null, vimperator.modes.ESCAPE_ONE_KEY); + return true; + } + // handle Escape-all-keys mode (I) if (vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS)) { - vimperator.removeMode(null, vimperator.modes.ESCAPE_ALL_KEYS); - return; + if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY)) + vimperator.removeMode(null, vimperator.modes.ESCAPE_ONE_KEY); // and then let flow continue + else if (key == "" || key == "" || key == "") + ; // let flow continue to handle these keys + else + return true; } - vimperator.setMode(vimperator.modes.NORMAL); - vimperator.commandline.clear(); - vimperator.hints.disableHahMode(); - vimperator.statusline.updateUrl(); - vimperator.focusContent(); - } - } + // FIXME: proper way is to have a better onFocus handler which also handles events for the XUL + if (!vimperator.hasMode(vimperator.modes.COMMAND_LINE) && + isFormElemFocused()) // non insert mode, but e.g. the location bar has focus + return true; - // this keypress handler gets always called first, even if e.g. - // the commandline has focus - this.onKeyPress = function (event) - { - var key = vimperator.events.toString(event); - if (!key) - return true; - - var stop = true; // set to false if we should NOT consume this event but let also firefox handle it - - var win = document.commandDispatcher.focusedWindow; - if (win && win.document.designMode == "on") - return true; - - if (vimperator.hasMode(vimperator.modes.MENU)) - return true; - - // XXX: for now only, later: input mappings if form element focused - if (isFormElemFocused()) - { - if (key == "") + if (vimperator.hasMode(vimperator.modes.COMMAND_LINE) && + vimperator.hasMode(vimperator.modes.WRITE_MULTILINE)) { - var elt = window.document.commandDispatcher.focusedElement; - - if (elt.setSelectionRange && readFromClipboard()) - // readFromClipboard would return 'undefined' if not checked - // dunno about .setSelectionRange - { - var rangeStart = elt.selectionStart; // caret position - var rangeEnd = elt.selectionEnd; - var tempStr1 = elt.value.substring(0,rangeStart); - var tempStr2 = readFromClipboard(); - var tempStr3 = elt.value.substring(rangeEnd); - elt.value = tempStr1 + tempStr2 + tempStr3; - elt.selectionStart = rangeStart + tempStr2.length; - elt.selectionEnd = elt.selectionStart; - event.preventDefault(); - // prevents additional firefox-clipboard pasting - } - } - return false; - } - - // handle Escape-one-key mode (Ctrl-v) - if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY) && !vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS)) - { - vimperator.removeMode(null, vimperator.modes.ESCAPE_ONE_KEY); - return true; - } - // handle Escape-all-keys mode (I) - if (vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS)) - { - if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY)) - vimperator.removeMode(null, vimperator.modes.ESCAPE_ONE_KEY); // and then let flow continue - else if (key == "" || key == "" || key == "") - ; // let flow continue to handle these keys - else - return true; - } - - // FIXME: proper way is to have a better onFocus handler which also handles events for the XUL - if (!vimperator.hasMode(vimperator.modes.COMMAND_LINE) && - isFormElemFocused()) // non insert mode, but e.g. the location bar has focus - return true; - - if (vimperator.hasMode(vimperator.modes.COMMAND_LINE) && - vimperator.hasMode(vimperator.modes.WRITE_MULTILINE)) - { - vimperator.commandline.onMultilineOutputEvent(event); - return false; - } - - // XXX: ugly hack for now pass certain keys to firefox as they are without beeping - // also fixes key navigation in combo boxes, etc. - if (vimperator.hasMode(vimperator.modes.NORMAL)) - { - if (key == "" || key == "" || key == "" || key == "" || key == "" || key == "") + vimperator.commandline.onMultilineOutputEvent(event); return false; - } - - - // // FIXME: handle middle click in content area {{{ - // // alert(event.target.id); - // if (/*event.type == 'mousedown' && */event.button == 1 && event.target.id == 'content') - // { - // //echo("foo " + event.target.id); - // //if (document.commandDispatcher.focusedElement == command_line.inputField) - // { - // //alert(command_line.value.substring(0, command_line.selectionStart)); - // command_line.value = command_line.value.substring(0, command_line.selectionStart) + - // readFromClipboard() + - // command_line.value.substring(command_line.selectionEnd, command_line.value.length); - // alert(command_line.value); - // } - // //else - // // { - // // openURLs(readFromClipboard()); - // // } - // return true; - // } }}} - - - // if Hit-a-hint mode is on, special handling of keys is required - // FIXME: total mess - if (vimperator.hasMode(vimperator.modes.HINTS)) - { - // never propagate this key to firefox, when hints are visible - //event.preventDefault(); - //event.stopPropagation(); - - var map = vimperator.mappings.get(vimperator.modes.HINTS, key); - if (map) - { - if (map.always_active || vimperator.hints.currentState() == 1) - { - map.execute(null, vimperator.input.count); - if (map.cancel_mode) // stop processing this event - { - vimperator.hints.disableHahMode(); - vimperator.input.buffer = ""; - vimperator.statusline.updateInputBuffer(""); - return false; - } - else - { - // FIXME: make sure that YOU update the statusbar message yourself - // first in g_hint_mappings when in this mode! - vimperator.statusline.updateInputBuffer(vimperator.input.buffer); - return false; - } - } } - // no mapping found, beep() - if (vimperator.hints.currentState() == 1) + // XXX: ugly hack for now pass certain keys to firefox as they are without beeping + // also fixes key navigation in combo boxes, etc. + if (vimperator.hasMode(vimperator.modes.NORMAL)) { - vimperator.beep(); - vimperator.hints.disableHahMode(); - vimperator.input.buffer = ""; + if (key == "" || key == "" || key == "" || key == "" || key == "" || key == "") + return false; + } + + + // // FIXME: handle middle click in content area {{{ + // // alert(event.target.id); + // if (/*event.type == 'mousedown' && */event.button == 1 && event.target.id == 'content') + // { + // //echo("foo " + event.target.id); + // //if (document.commandDispatcher.focusedElement == command_line.inputField) + // { + // //alert(command_line.value.substring(0, command_line.selectionStart)); + // command_line.value = command_line.value.substring(0, command_line.selectionStart) + + // readFromClipboard() + + // command_line.value.substring(command_line.selectionEnd, command_line.value.length); + // alert(command_line.value); + // } + // //else + // // { + // // openURLs(readFromClipboard()); + // // } + // return true; + // } }}} + + + // if Hit-a-hint mode is on, special handling of keys is required + // FIXME: total mess + if (vimperator.hasMode(vimperator.modes.HINTS)) + { + // never propagate this key to firefox, when hints are visible + //event.preventDefault(); + //event.stopPropagation(); + + var map = vimperator.mappings.get(vimperator.modes.HINTS, key); + if (map) + { + if (map.alwaysActive || vimperator.hints.currentState() == 1) + { + map.execute(null, vimperator.input.count); + if (map.cancelMode) // stop processing this event + { + vimperator.hints.disableHahMode(); + vimperator.input.buffer = ""; + vimperator.statusline.updateInputBuffer(""); + return false; + } + else + { + // FIXME: make sure that YOU update the statusbar message yourself + // first in g_hint_mappings when in this mode! + vimperator.statusline.updateInputBuffer(vimperator.input.buffer); + return false; + } + } + } + + // no mapping found, beep() + if (vimperator.hints.currentState() == 1) + { + vimperator.beep(); + vimperator.hints.disableHahMode(); + vimperator.input.buffer = ""; + vimperator.statusline.updateInputBuffer(vimperator.input.buffer); + return true; + } + + // if we came here, let hit-a-hint process the key as it is part + // of a partial link + var res = vimperator.hints.processEvent(event); + if (res < 0) // error occured processing this key + { + vimperator.beep(); + if (vimperator.hasMode(vimperator.modes.QUICK_HINT)) + vimperator.hints.disableHahMode(); + else // ALWAYS mode + vimperator.hints.resetHintedElements(); + vimperator.input.buffer = ""; + } + else if (res == 0 || vimperator.hasMode(vimperator.modes.EXTENDED_HINT)) // key processed, part of a larger hint + vimperator.input.buffer += key; + else // this key completed a quick hint + { + // if the hint is all in UPPERCASE, open it in new tab + vimperator.input.buffer += key; + if (/[A-Za-z]/.test(vimperator.input.buffer) && vimperator.input.buffer.toUpperCase() == vimperator.input.buffer) + vimperator.hints.openHints(true, false); + else // open in current window + vimperator.hints.openHints(false, false); + + if (vimperator.hasMode(vimperator.modes.QUICK_HINT)) + vimperator.hints.disableHahMode(); + else // ALWAYS mode + vimperator.hints.resetHintedElements(); + + vimperator.input.buffer = ""; + } + vimperator.statusline.updateInputBuffer(vimperator.input.buffer); return true; } - // if we came here, let hit-a-hint process the key as it is part - // of a partial link - var res = vimperator.hints.processEvent(event); - if (res < 0) // error occured processing this key - { - vimperator.beep(); - if (vimperator.hasMode(vimperator.modes.QUICK_HINT)) - vimperator.hints.disableHahMode(); - else // ALWAYS mode - vimperator.hints.resetHintedElements(); - vimperator.input.buffer = ""; - } - else if (res == 0 || vimperator.hasMode(vimperator.modes.EXTENDED_HINT)) // key processed, part of a larger hint - vimperator.input.buffer += key; - else // this key completed a quick hint - { - // if the hint is all in UPPERCASE, open it in new tab - vimperator.input.buffer += key; - if (/[A-Za-z]/.test(vimperator.input.buffer) && vimperator.input.buffer.toUpperCase() == vimperator.input.buffer) - vimperator.hints.openHints(true, false); - else // open in current window - vimperator.hints.openHints(false, false); - - if (vimperator.hasMode(vimperator.modes.QUICK_HINT)) - vimperator.hints.disableHahMode(); - else // ALWAYS mode - vimperator.hints.resetHintedElements(); - - vimperator.input.buffer = ""; - } - - vimperator.statusline.updateInputBuffer(vimperator.input.buffer); - return true; - } - - var count_str = vimperator.input.buffer.match(/^[0-9]*/)[0]; - var candidate_command = (vimperator.input.buffer + key).replace(count_str, ""); - var map; - if (event.noremap) - map = vimperator.mappings.getDefaultMap(vimperator.modes.NORMAL, candidate_command); - else - map = vimperator.mappings.get(vimperator.modes.NORMAL, candidate_command); - - // counts must be at the start of a complete mapping (10j -> go 10 lines down) - if ((vimperator.input.buffer + key).match(/^[1-9][0-9]*$/)) - { - // no count for insert mode mappings - if (vimperator.hasMode(vimperator.modes.COMMAND_LINE)) - stop = false; + var countStr = vimperator.input.buffer.match(/^[0-9]*/)[0]; + var candidateCommand = (vimperator.input.buffer + key).replace(countStr, ""); + var map; + if (event.noremap) + map = vimperator.mappings.getDefaultMap(vimperator.modes.NORMAL, candidateCommand); else - vimperator.input.buffer += key; - } - else if (vimperator.input.pendingArgMap) - { - vimperator.input.buffer = ""; + map = vimperator.mappings.get(vimperator.modes.NORMAL, candidateCommand); - if (key != "" && key != "") - vimperator.input.pendingArgMap.execute(null, vimperator.input.count, key); - - vimperator.input.pendingArgMap = null; - } - else if (map) - { - vimperator.input.count = parseInt(count_str, 10); - if (isNaN(vimperator.input.count)) - vimperator.input.count = -1; - if (map.flags & vimperator.Mappings.flags.ARGUMENT) + // counts must be at the start of a complete mapping (10j -> go 10 lines down) + if ((vimperator.input.buffer + key).match(/^[1-9][0-9]*$/)) { - vimperator.input.pendingArgMap = map; - vimperator.input.buffer += key; + // no count for insert mode mappings + if (vimperator.hasMode(vimperator.modes.COMMAND_LINE)) + stop = false; + else + vimperator.input.buffer += key; } - else if (vimperator.input.pendingMotionMap) + else if (vimperator.input.pendingArgMap) { + vimperator.input.buffer = ""; + if (key != "" && key != "") - { - vimperator.input.pendingMotionMap.execute(candidate_command, vimperator.input.count, null); - } - vimperator.input.pendingMotionMap = null; - vimperator.input.buffer = ""; + vimperator.input.pendingArgMap.execute(null, vimperator.input.count, key); + + vimperator.input.pendingArgMap = null; } - // no count support for these commands yet - else if (map.flags & vimperator.Mappings.flags.MOTION) + else if (map) { - vimperator.input.pendingMotionMap = map; - vimperator.input.buffer = ""; + vimperator.input.count = parseInt(countStr, 10); + if (isNaN(vimperator.input.count)) + vimperator.input.count = -1; + if (map.flags & vimperator.Mappings.flags.ARGUMENT) + { + vimperator.input.pendingArgMap = map; + vimperator.input.buffer += key; + } + else if (vimperator.input.pendingMotionMap) + { + if (key != "" && key != "") + { + vimperator.input.pendingMotionMap.execute(candidateCommand, vimperator.input.count, null); + } + vimperator.input.pendingMotionMap = null; + vimperator.input.buffer = ""; + } + // no count support for these commands yet + else if (map.flags & vimperator.Mappings.flags.MOTION) + { + vimperator.input.pendingMotionMap = map; + vimperator.input.buffer = ""; + } + else + { + vimperator.input.buffer = ""; + map.execute(null, vimperator.input.count); + } + } + else if (vimperator.mappings.getCandidates(vimperator.modes.NORMAL, candidateCommand).length > 0) + { + vimperator.input.buffer += key; } else { vimperator.input.buffer = ""; - map.execute(null, vimperator.input.count); + vimperator.input.pendingArgMap = null; + vimperator.input.pendingMotionMap = null; + + // allow key to be passed to firefox if we can't handle it + stop = false; + + // TODO: see if this check is needed or are all motion commands already mapped in these modes? + if (!vimperator.hasMode(vimperator.modes.COMMAND_LINE)) + vimperator.beep(); } - } - else if (vimperator.mappings.getCandidates(vimperator.modes.NORMAL, candidate_command).length > 0) - { - vimperator.input.buffer += key; - } - else - { - vimperator.input.buffer = ""; - vimperator.input.pendingArgMap = null; - vimperator.input.pendingMotionMap = null; - // allow key to be passed to firefox if we can't handle it - stop = false; + if (stop) + { + event.preventDefault(); + event.stopPropagation(); + } - // TODO: see if this check is needed or are all motion commands already mapped in these modes? - if (!vimperator.hasMode(vimperator.modes.COMMAND_LINE)) - vimperator.beep(); - } + var motionMap = (vimperator.input.pendingMotionMap && vimperator.input.pendingMotionMap.names[0]) || ""; + vimperator.statusline.updateInputBuffer(motionMap + vimperator.input.buffer); + return false; + }, - if (stop) + // this is need for sites like msn.com which focus the input field on keydown + onKeyUpOrDown: function (event) { - event.preventDefault(); + if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY) || vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS) || isFormElemFocused()) + return true; + event.stopPropagation(); + return false; + }, + + progressListener: { + QueryInterface: function (aIID) + { + if (aIID.equals(Components.interfaces.nsIWebProgressListener) || + aIID.equals(Components.interfaces.nsIXULBrowserWindow) || // for setOverLink(); + aIID.equals(Components.interfaces.nsISupportsWeakReference) || + aIID.equals(Components.interfaces.nsISupports)) + return this; + throw Components.results.NS_NOINTERFACE; + }, + + // XXX: function may later be needed to detect a canceled synchronous openURL() + onStateChange: function (webProgress, aRequest, flags, aStatus) + { + // 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 & (Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT | + Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW)) + { + // This fires when the load event is initiated + if (flags & Components.interfaces.nsIWebProgressListener.STATE_START) + { + vimperator.statusline.updateProgress(0); + } + else if (flags & Components.interfaces.nsIWebProgressListener.STATE_STOP) + ;// vimperator.statusline.updateUrl(); + } + }, + // for notifying the user about secure web pages + onSecurityChange: function (webProgress, aRequest, aState) + { + const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; + if (aState & nsIWebProgressListener.STATE_IS_INSECURE) + vimperator.statusline.setClass("insecure"); + else if (aState & nsIWebProgressListener.STATE_IS_BROKEN) + vimperator.statusline.setClass("broken"); + else if (aState & nsIWebProgressListener.STATE_IS_SECURE) + vimperator.statusline.setClass("secure"); + }, + onStatusChange: function (webProgress, request, status, message) + { + vimperator.statusline.updateUrl(message); + }, + onProgressChange: function (webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) + { + vimperator.statusline.updateProgress(curTotalProgress/maxTotalProgress); + }, + // happens when the users switches tabs + onLocationChange: function () + { + vimperator.statusline.updateUrl(); + vimperator.statusline.updateProgress(); + + // if this is not delayed we get the position of the old buffer + setTimeout(function () { vimperator.statusline.updateBufferPosition(); }, 100); + }, + // called at the very end of a page load + asyncUpdateUI: function () + { + setTimeout(vimperator.statusline.updateUrl, 100); + }, + setOverLink : function (link, b) + { + var ssli = vimperator.options["showstatuslinks"]; + if (link && ssli) + { + if (ssli == 1) + vimperator.statusline.updateUrl("Link: " + link); + else if (ssli == 2) + vimperator.echo("Link: " + link, vimperator.commandline.DISALLOW_MULTILINE); + } + + if (link == "") + { + if (ssli == 1) + vimperator.statusline.updateUrl(); + else if (ssli == 2) + vimperator.setMode(); // trick to reshow the mode in the command line + } + }, + + // stub functions for the interfaces + setJSStatus: function (status) { ; }, + setJSDefaultStatus: function (status) { ; }, + setDefaultStatus: function (status) { ; }, + onLinkIconAvailable: function () { ; } } - var motion_map = (vimperator.input.pendingMotionMap && vimperator.input.pendingMotionMap.names[0]) || ""; - vimperator.statusline.updateInputBuffer(motion_map + vimperator.input.buffer); - return false; - } - window.addEventListener("keypress", this.onKeyPress, true); - - // this is need for sites like msn.com which focus the input field on keydown - this.onKeyUpOrDown = function (event) - { - if (vimperator.hasMode(vimperator.modes.ESCAPE_ONE_KEY) || vimperator.hasMode(vimperator.modes.ESCAPE_ALL_KEYS) || isFormElemFocused()) - return true; - - event.stopPropagation(); - return false; - } - window.addEventListener("keydown", this.onKeyUpOrDown, true); - window.addEventListener("keyup", this.onKeyUpOrDown, true); - - this.progressListener = - { - QueryInterface: function (aIID) - { - if (aIID.equals(Components.interfaces.nsIWebProgressListener) || - aIID.equals(Components.interfaces.nsIXULBrowserWindow) || // for setOverLink(); - aIID.equals(Components.interfaces.nsISupportsWeakReference) || - aIID.equals(Components.interfaces.nsISupports)) - return this; - throw Components.results.NS_NOINTERFACE; - }, - - // XXX: function may later be needed to detect a canceled synchronous openURL() - onStateChange: function (webProgress, aRequest, flags, aStatus) - { - // 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 & (Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT | - Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW)) - { - // This fires when the load event is initiated - if (flags & Components.interfaces.nsIWebProgressListener.STATE_START) - { - vimperator.statusline.updateProgress(0); - } - else if (flags & Components.interfaces.nsIWebProgressListener.STATE_STOP) - ;// vimperator.statusline.updateUrl(); - } - }, - // for notifying the user about secure web pages - onSecurityChange: function (webProgress, aRequest, aState) - { - const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; - if (aState & nsIWebProgressListener.STATE_IS_INSECURE) - vimperator.statusline.setClass("insecure"); - else if (aState & nsIWebProgressListener.STATE_IS_BROKEN) - vimperator.statusline.setClass("broken"); - else if (aState & nsIWebProgressListener.STATE_IS_SECURE) - vimperator.statusline.setClass("secure"); - }, - onStatusChange: function (webProgress, request, status, message) - { - vimperator.statusline.updateUrl(message); - }, - onProgressChange: function (webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) - { - vimperator.statusline.updateProgress(curTotalProgress/maxTotalProgress); - }, - // happens when the users switches tabs - onLocationChange: function () - { - vimperator.statusline.updateUrl(); - vimperator.statusline.updateProgress(); - - // if this is not delayed we get the position of the old buffer - setTimeout(function () { vimperator.statusline.updateBufferPosition(); }, 100); - }, - // called at the very end of a page load - asyncUpdateUI: function () - { - setTimeout(vimperator.statusline.updateUrl, 100); - }, - setOverLink : function (link, b) - { - var ssli = vimperator.options["showstatuslinks"]; - if (link && ssli) - { - if (ssli == 1) - vimperator.statusline.updateUrl("Link: " + link); - else if (ssli == 2) - vimperator.echo("Link: " + link, vimperator.commandline.DISALLOW_MULTILINE); - } - - if (link == "") - { - if (ssli == 1) - vimperator.statusline.updateUrl(); - else if (ssli == 2) - vimperator.setMode(); // trick to reshow the mode in the command line - } - }, - - // stub functions for the interfaces - setJSStatus: function (status) { ; }, - setJSDefaultStatus: function (status) { ; }, - setDefaultStatus: function (status) { ; }, - onLinkIconAvailable: function () { ; } }; - window.XULBrowserWindow = this.progressListener; + window.XULBrowserWindow = eventManager.progressListener; window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebNavigation) .QueryInterface(Components.interfaces.nsIDocShellTreeItem).treeOwner .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIXULWindow) .XULBrowserWindow = window.XULBrowserWindow; - getBrowser().addProgressListener(this.progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL); + getBrowser().addProgressListener(eventManager.progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL); + + window.addEventListener("keypress", eventManager.onKeyPress, true); + window.addEventListener("keydown", eventManager.onKeyUpOrDown, true); + window.addEventListener("keyup", eventManager.onKeyUpOrDown, true); + + return eventManager; //}}} -} //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/find.js b/content/find.js index ed0ad6fc..ecc4c24e 100644 --- a/content/find.js +++ b/content/find.js @@ -39,27 +39,32 @@ the terms of any one of the MPL, the GPL or the LGPL. // make sure you only create this object when the "vimperator" object is ready vimperator.Search = function () //{{{ { - var self = this; // needed for callbacks since "this" is the "vimperator" object in a callback - var found = false; // true if the last search was successful - var backwards = false; // currently searching backwards - var search_string = ""; // current search string (without modifiers) - var search_pattern = ""; // current search string (includes modifiers) - var last_search_pattern = ""; // the last searched pattern (includes modifiers) - var last_search_string = ""; // the last searched string (without modifiers) - var last_search_backwards = false; // like "backwards", but for the last search, so if you cancel a search with this is not set - var case_sensitive = false; // search string is case sensitive - var links_only = false; // search is limited to link text only + //////////////////////////////////////////////////////////////////////////////// + ////////////////////// PRIVATE SECTION ///////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + // FIXME: + //var self = this; // needed for callbacks since "this" is the "vimperator" object in a callback + var found = false; // true if the last search was successful + var backwards = false; // currently searching backwards + var searchString = ""; // current search string (without modifiers) + var searchPattern = ""; // current search string (includes modifiers) + var lastSearchPattern = ""; // the last searched pattern (includes modifiers) + var lastSearchString = ""; // the last searched string (without modifiers) + var lastSearchBackwards = false; // like "backwards", but for the last search, so if you cancel a search with this is not set + var caseSensitive = false; // search string is case sensitive + var linksOnly = false; // search is limited to link text only // Event handlers for search - closure is needed - vimperator.registerCallback("change", vimperator.modes.SEARCH_FORWARD, function (command) { self.searchKeyPressed(command); }); - vimperator.registerCallback("submit", vimperator.modes.SEARCH_FORWARD, function (command) { self.searchSubmitted(command); }); - vimperator.registerCallback("cancel", vimperator.modes.SEARCH_FORWARD, function () { self.searchCanceled(); }); + vimperator.registerCallback("change", vimperator.modes.SEARCH_FORWARD, function (command) { vimperator.search.searchKeyPressed(command); }); + vimperator.registerCallback("submit", vimperator.modes.SEARCH_FORWARD, function (command) { vimperator.search.searchSubmitted(command); }); + vimperator.registerCallback("cancel", vimperator.modes.SEARCH_FORWARD, function () { vimperator.search.searchCanceled(); }); // TODO: allow advanced modes in register/triggerCallback - vimperator.registerCallback("change", vimperator.modes.SEARCH_BACKWARD, function (command) { self.searchKeyPressed(command); }); - vimperator.registerCallback("submit", vimperator.modes.SEARCH_BACKWARD, function (command) { self.searchSubmitted(command); }); - vimperator.registerCallback("cancel", vimperator.modes.SEARCH_BACKWARD, function () { self.searchCanceled(); }); + vimperator.registerCallback("change", vimperator.modes.SEARCH_BACKWARD, function (command) { vimperator.search.searchKeyPressed(command); }); + vimperator.registerCallback("submit", vimperator.modes.SEARCH_BACKWARD, function (command) { vimperator.search.searchSubmitted(command); }); + vimperator.registerCallback("cancel", vimperator.modes.SEARCH_BACKWARD, function () { vimperator.search.searchCanceled(); }); - // set search_string, search_pattern, case_sensitive, links_only + // set searchString, searchPattern, caseSensitive, linksOnly function processUserPattern(pattern) { // strip off pattern terminator and offset @@ -68,32 +73,32 @@ vimperator.Search = function () //{{{ else pattern = pattern.replace(/\/.*/, ""); - search_pattern = pattern; + searchPattern = pattern; // links only search - \l wins if both modifiers specified if (/\\l/.test(pattern)) - links_only = false; + linksOnly = false; else if (/\L/.test(pattern)) - links_only = true; + linksOnly = true; else if (vimperator.options["linksearch"]) - links_only = true; + linksOnly = true; else - links_only = false; + linksOnly = false; // strip links-only modifiers pattern = pattern.replace(/(\\)?\\[lL]/g, function ($0, $1) { return $1 ? $0 : ""; }); // case sensitivity - \c wins if both modifiers specified if (/\c/.test(pattern)) - case_sensitive = false; + caseSensitive = false; else if (/\C/.test(pattern)) - case_sensitive = true; + caseSensitive = true; else if (vimperator.options["ignorecase"] && vimperator.options["smartcase"] && /[A-Z]/.test(pattern)) - case_sensitive = true; + caseSensitive = true; else if (vimperator.options["ignorecase"]) - case_sensitive = false; + caseSensitive = false; else - case_sensitive = true; + caseSensitive = true; // strip case-sensitive modifiers pattern = pattern.replace(/(\\)?\\[cC]/g, function ($0, $1) { return $1 ? $0 : ""; }); @@ -101,171 +106,179 @@ vimperator.Search = function () //{{{ // remove any modifer escape \ pattern = pattern.replace(/\\(\\[cClL])/g, "$1"); - search_string = pattern; + searchString = pattern; } - // Called when the search dialog is asked for - // If you omit "mode", it will default to forward searching - this.openSearchDialog = function (mode) - { - if (mode == vimperator.modes.SEARCH_BACKWARD) + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// PUBLIC SECTION ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + return { + + // Called when the search dialog is asked for + // If you omit "mode", it will default to forward searching + openSearchDialog: function (mode) { - vimperator.commandline.open("?", "", vimperator.modes.SEARCH_BACKWARD); - backwards = true; - } - else + if (mode == vimperator.modes.SEARCH_BACKWARD) + { + vimperator.commandline.open("?", "", vimperator.modes.SEARCH_BACKWARD); + backwards = true; + } + else + { + vimperator.commandline.open("/", "", vimperator.modes.SEARCH_FORWARD); + backwards = false; + } + + // TODO: focus the top of the currently visible screen + }, + + // Finds text in a page + // TODO: backwards seems impossible i fear :( + find: function (str, backwards) { - vimperator.commandline.open("/", "", vimperator.modes.SEARCH_FORWARD); - backwards = false; - } + var fastFind = getBrowser().fastFind; - // TODO: focus the top of the currently visible screen - } + processUserPattern(str); - // Finds text in a page - // TODO: backwards seems impossible i fear :( - this.find = function (str, backwards) - { - var fastFind = getBrowser().fastFind; + fastFind.caseSensitive = caseSensitive; + found = fastFind.find(searchString, linksOnly) != Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND; - processUserPattern(str); + if (!found) + setTimeout(function () { vimperator.echoerr("E486: Pattern not found: " + searchPattern); }, 0); - fastFind.caseSensitive = case_sensitive; - found = fastFind.find(search_string, links_only) != Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND; + return found; + }, - if (!found) - setTimeout(function () { vimperator.echoerr("E486: Pattern not found: " + search_pattern); }, 0); - - return found; - } - - // Called when the current search needs to be repeated - this.findAgain = function (reverse) - { - // this hack is needed to make n/N work with the correct string, if - // we typed /foo after the original search. Since searchString is - // readonly we have to call find() again to update it. - if (getBrowser().fastFind.searchString != last_search_string) - this.find(last_search_string, false); - - var up = reverse ? !last_search_backwards : last_search_backwards; - var result; - - if (up) - result = getBrowser().fastFind.findPrevious(); - else - result = getBrowser().fastFind.findNext(); - - if (result == Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND) + // Called when the current search needs to be repeated + findAgain: function (reverse) { - vimperator.echoerr("E486: Pattern not found: " + last_search_pattern); - } - else if (result == Components.interfaces.nsITypeAheadFind.FIND_WRAPPED) + // this hack is needed to make n/N work with the correct string, if + // we typed /foo after the original search. Since searchString is + // readonly we have to call find() again to update it. + if (getBrowser().fastFind.searchString != lastSearchString) + this.find(lastSearchString, false); + + var up = reverse ? !lastSearchBackwards : lastSearchBackwards; + var result; + + if (up) + result = getBrowser().fastFind.findPrevious(); + else + result = getBrowser().fastFind.findNext(); + + if (result == Components.interfaces.nsITypeAheadFind.FIND_NOTFOUND) + { + vimperator.echoerr("E486: Pattern not found: " + lastSearchPattern); + } + else if (result == Components.interfaces.nsITypeAheadFind.FIND_WRAPPED) + { + // hack needed, because wrapping causes a "scroll" event which clears + // our command line + setTimeout(function () { + if (up) + vimperator.commandline.echo("search hit TOP, continuing at BOTTOM", vimperator.commandline.HL_WARNING); + else + vimperator.commandline.echo("search hit BOTTOM, continuing at TOP", vimperator.commandline.HL_WARNING); + }, 0); + } + else + { + vimperator.echo((up ? "?" : "/") + lastSearchPattern); + + if (vimperator.options["hlsearch"]) + this.highlight(lastSearchString); + } + }, + + // Called when the user types a key in the search dialog. Triggers a find attempt if 'incsearch' is set + searchKeyPressed: function (command) { - // hack needed, because wrapping causes a "scroll" event which clears - // our command line - setTimeout(function () { - if (up) - vimperator.commandline.echo("search hit TOP, continuing at BOTTOM", vimperator.commandline.HL_WARNING); - else - vimperator.commandline.echo("search hit BOTTOM, continuing at TOP", vimperator.commandline.HL_WARNING); - }, 0); - } - else + if (vimperator.options["incsearch"]) + this.find(command, backwards); + }, + + // Called when the enter key is pressed to trigger a search + // use forcedBackward if you call this function directly + searchSubmitted: function (command, forcedBackward) { - vimperator.echo((up ? "?" : "/") + last_search_pattern); + if (typeof forcedBackward === "boolean") + backwards = forcedBackward; + + // use the last pattern if none specified + if (!command) + command = lastSearchPattern; + + this.clear(); + this.find(command, backwards); + + lastSearchBackwards = backwards; + lastSearchPattern = command.replace(backwards ? /\?.*/ : /\/.*/, ""); // XXX + lastSearchString = searchString; + + // TODO: move to find() when reverse incremental searching is kludged in + // need to find again for reverse searching + if (backwards) + setTimeout(function () { vimperator.search.findAgain(false); }, 0); if (vimperator.options["hlsearch"]) - this.highlight(last_search_string); - } - } + this.highlight(searchString); - // Called when the user types a key in the search dialog. Triggers a find attempt if 'incsearch' is set - this.searchKeyPressed = function (command) - { - if (vimperator.options["incsearch"]) - this.find(command, backwards); - } + vimperator.setMode(vimperator.modes.NORMAL); + vimperator.focusContent(); + }, - // Called when the enter key is pressed to trigger a search - // use forced_direction if you call this function directly - this.searchSubmitted = function (command, forced_backward) - { - if (typeof forced_backward === "boolean") - backwards = forced_backward; - - // use the last pattern if none specified - if (!command) - command = last_search_pattern; - - this.clear(); - this.find(command, backwards); - - last_search_backwards = backwards; - last_search_pattern = command.replace(backwards ? /\?.*/ : /\/.*/, ""); // XXX - last_search_string = search_string; - - // TODO: move to find() when reverse incremental searching is kludged in - // need to find again for reverse searching - if (backwards) - setTimeout(function () { self.findAgain(false); }, 0); - - if (vimperator.options["hlsearch"]) - this.highlight(search_string); - - vimperator.setMode(vimperator.modes.NORMAL); - vimperator.focusContent(); - } - - // Called when the search is cancelled - for example if someone presses - // escape while typing a search - this.searchCanceled = function () - { - //removeMode(MODE_SEARCH); - vimperator.setMode(vimperator.modes.NORMAL); - vimperator.focusContent(); - } - - this.highlight = function (text) - { - // already highlighted? - if (window.content.document.getElementById("__firefox-findbar-search-id")) - return; - - if (!text) - text = last_search_string; - - // NOTE: gFindBar.setCaseSensitivity() in FF2 does NOT set the - // accessibility.typeaheadfind.casesensitive pref as needed by - // highlightDoc() - gFindBar.mTypeAheadCaseSensitive = case_sensitive ? 1 : 0; - gFindBar.highlightDoc("white", "black", text); - - // TODO: seems fast enough for now...just - // NOTE: FF2 highlighting spans all have the same id rather than a class attribute - (function (win) + // Called when the search is cancelled - for example if someone presses + // escape while typing a search + searchCanceled: function () { - for (var i = 0; i < win.frames.length; i++) - arguments.callee(win.frames[i]); - var spans = vimperator.buffer.evaluateXPath("//span[@id='__firefox-findbar-search-id']", win.document); - for (var i = 0; i < spans.snapshotLength; i++) - spans.snapshotItem(i).setAttribute("style", vimperator.options["hlsearchstyle"]); - })(window.content); + //removeMode(MODE_SEARCH); + vimperator.setMode(vimperator.modes.NORMAL); + vimperator.focusContent(); + }, - // recreate selection since _highlightDoc collapses the selection backwards - getBrowser().fastFind.findNext(); + highlight: function (text) + { + // already highlighted? + if (window.content.document.getElementById("__firefox-findbar-search-id")) + return; - // TODO: remove highlighting from non-link matches (HTML - A/AREA with href attribute; XML - Xlink [@type="simple"]) - } + if (!text) + text = lastSearchString; - this.clear = function () - { - gFindBar.highlightDoc(); - // need to manually collapse the selection if the document is not - // highlighted - getBrowser().fastFind.collapseSelection(); - } + // NOTE: gFindBar.setCaseSensitivity() in FF2 does NOT set the + // accessibility.typeaheadfind.casesensitive pref as needed by + // highlightDoc() + gFindBar.mTypeAheadCaseSensitive = caseSensitive ? 1 : 0; + gFindBar.highlightDoc("white", "black", text); -} //}}} + // TODO: seems fast enough for now...just + // NOTE: FF2 highlighting spans all have the same id rather than a class attribute + (function (win) + { + for (var i = 0; i < win.frames.length; i++) + arguments.callee(win.frames[i]); + var spans = vimperator.buffer.evaluateXPath("//span[@id='__firefox-findbar-search-id']", win.document); + for (var i = 0; i < spans.snapshotLength; i++) + spans.snapshotItem(i).setAttribute("style", vimperator.options["hlsearchstyle"]); + })(window.content); + + // recreate selection since _highlightDoc collapses the selection backwards + getBrowser().fastFind.findNext(); + + // TODO: remove highlighting from non-link matches (HTML - A/AREA with href attribute; XML - Xlink [@type="simple"]) + }, + + clear: function () + { + gFindBar.highlightDoc(); + // need to manually collapse the selection if the document is not + // highlighted + getBrowser().fastFind.collapseSelection(); + } + + }; + //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/help.js b/content/help.js index e5aa4e67..754bb9e3 100644 --- a/content/help.js +++ b/content/help.js @@ -52,7 +52,7 @@ vimperator.help = function (section, easter) //{{{ { // the usage information for the command ret += ''; - for (var j=0; j < command.usage.length; j++) + for (var j = 0; j < command.usage.length; j++) { var usage = command.usage[j]; @@ -72,10 +72,10 @@ vimperator.help = function (section, easter) //{{{ ret += ''; // the actual help text with the first line in bold - if (command.short_help) + if (command.shortHelp) { ret += ''; - ret += command.short_help; // the help description + ret += command.shortHelp; // the help description ret += "
    "; if (func) // for options we print default values here, e.g. { @@ -93,11 +93,11 @@ vimperator.help = function (section, easter) //{{{ // the tags which are printed on the top right ret += ''; var names = command.names; - for (var j=0; j < names.length; j++) + for (var j = 0; j < names.length; j++) { - var cmd_name = names[j]; - cmd_name = vimperator.util.escapeHTML(cmd_name); - ret += '' + beg + cmd_name + end + '
    '; + var cmdName = names[j]; + cmdName = vimperator.util.escapeHTML(cmdName); + ret += '' + beg + cmdName + end + '
    '; } ret += ''; @@ -114,17 +114,17 @@ vimperator.help = function (section, easter) //{{{ ret = command.type + ' (default: '; if (command.type == "boolean") { - if (command.default_value == true) + if (command.defaultValue == true) ret += "on"; else ret += "off"; } else { - if (typeof command.default_value == "string" && command.default_value.length == 0) + if (typeof command.defaultValue == "string" && command.defaultValue.length == 0) ret += "''"; else - ret += command.default_value; + ret += command.defaultValue; } ret += ")
    "; @@ -286,6 +286,6 @@ vimperator.help = function (section, easter) //{{{ window.content.scrollTo(0, pos[1]); } }, 0); -} //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/hints.js b/content/hints.js index bc887304..cbaad1ee 100644 --- a/content/hints.js +++ b/content/hints.js @@ -24,11 +24,11 @@ vimperator.Hints = function () //{{{ { - const HINT_PREFIX = "hah_hint_"; // prefix for the hint id + //////////////////////////////////////////////////////////////////////////////// + ////////////////////// PRIVATE SECTION ///////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ - this.hintedElements = function () { return hintedElems; }; - this.currentState = function () { return state;}; - this.setCurrentState = function (s) { state = s;}; + const HINT_PREFIX = "hah_hint_"; // prefix for the hint id var isHahModeEnabled = false; // is typing mode on var hintedElems = []; @@ -68,27 +68,6 @@ vimperator.Hints = function () //{{{ win.coordLoaderId = window.setTimeout("vimperator.hints.loadCoord(" + win.winId + ", 0);", 1); } - this.loadCoord = function (winId, i) - { - win = wins[winId]; - - // win.res is not ready when loading has not finished yet - if (!win.res) - return; - - var elem = win.res.snapshotItem(i); - - if (elem) - genElemCoords(elem); - - i++; - - if (i < win.res.snapshotLength && !isHahModeEnabled) - window.setTimeout("vimperator.hints.loadCoord(" + winId + ", "+ i +");", 1); - else - win.coordLoaderId = null; - }; - function genElemCoords(elem) { // NOTE: experiment for making the function faster, report problems @@ -101,7 +80,7 @@ vimperator.Hints = function () //{{{ //} //return; - if (typeof(elem.validCoord) != "undefined") + if (typeof elem.validCoord != "undefined") { if (elem.validCoord == elem.ownerDocument.validCoords) return; @@ -157,7 +136,7 @@ vimperator.Hints = function () //{{{ if (!hintContainer) return false; } - hintContainer.valid_hint_count = 0; // none of these hints should be visible initially + hintContainer.validHintCount = 0; // none of these hints should be visible initially var hints = hintContainer.childNodes; var maxhints = vimperator.options["maxhints"]; @@ -197,7 +176,7 @@ vimperator.Hints = function () //{{{ hintElem.style.left = elem.absoLeft + "px"; hintElem.refElem = elem; - hintContainer.valid_hint_count++; // one more visible hint in this frame + hintContainer.validHintCount++; // one more visible hint in this frame linkCount++; // and one more total hint } @@ -235,7 +214,7 @@ vimperator.Hints = function () //{{{ var hints = hintContainer.childNodes; var i, j; - for (i = 0; i < hintContainer.valid_hint_count; i++) + for (i = 0; i < hintContainer.validHintCount; i++) { hintText = formatHint(offset+i); hintElem = hints[i]; @@ -244,7 +223,7 @@ vimperator.Hints = function () //{{{ hintElem.innerHTML = hintText; hintElem.id = HINT_PREFIX + hintText; } - offset += hintContainer.valid_hint_count; + offset += hintContainer.validHintCount; // recursively show hints for (j = 0; j < win.frames.length; j++) @@ -260,7 +239,7 @@ vimperator.Hints = function () //{{{ win = window.content; var doc = win.document; - var res = vimperator.buffer.evaluateXPath("//HINTS/SPAN", doc) + var res = vimperator.buffer.evaluateXPath("//HINTS/SPAN", doc); var elem, i; for (i = 0; i < res.snapshotLength; i++) @@ -387,283 +366,6 @@ vimperator.Hints = function () //{{{ } } - //////////////////////////////////////////////////////////////////////////////// - // basic functionality - //////////////////////////////////////////////////////////////////////////////// - - /** - * Enables the HaH-mode by showing the hints and prepare to input the - * hint numbers - * - * @author Pekka Sillanpaa - * @param event that caused the mode to change - * @return -1 if already enabled - */ - //function enableHahMode(event, mode) - this.enableHahMode = function (mode) - { - vimperator.setMode(vimperator.modes.HINTS, mode); - state = 0; - linkCount = 0; - linkNumString = ""; - isHahModeEnabled = true; - - createHints(); - showHints(null, 0); - - return true; - } - - /** - * Disables the HaH-mode by hiding the hints and disabling the input mode - * - * @author Pekka Sillanpaa - * @param event that caused the mode to change - * @param action = true if something is to be clicked - * false if cancel - * @return -1 if already disabled - */ - //function disableHahMode(event) - this.disableHahMode = function (win) - { - if (!isHahModeEnabled) - return; - - vimperator.setMode(vimperator.modes.NORMAL); - isHahModeEnabled = false; - linkNumString = ""; - hintedElems = []; - - removeHints(win); - return 0; - }; - - this.resetHintedElements = function () - { - linkNumString = ""; - state = 0; - - while (hintedElems.length > 0) - { - var elem = hintedElems.pop(); - if (!elem) - return 0; - // reset style attribute - setHintStyle(elem, vimperator.options["hintstyle"]); - } - }; - - - this.reshowHints = function () - { - onResize(null); - - if (isHahModeEnabled) - { - removeHints(); - createHints(); - showHints(null, 0); - } - }; - - - // TODO: move these functions somewhere more general - - // this function 'click' an element, which also works - // for javascript links - this.openHints = function (new_tab, new_window) - { - var x = 0, y = 0; - - while (hintedElems.length > 0) - { - var elem = hintedElems.pop(); - if (!elem) - return 0; - - setHintStyle(elem, vimperator.options["hintstyle"]); - elem = elem.refElem; - var elemTagName = elem.localName.toLowerCase(); - elem.focus(); - - if (elemTagName == "frame" || elemTagName == "iframe") - return 0; - - // for imagemap - if (elemTagName == "area") - { - var coords = elem.getAttribute("coords").split(","); - x = Number(coords[0]); - y = Number(coords[1]); - } - var doc = window.content.document; - var view = window.document.defaultView; - - var evt = doc.createEvent("MouseEvents"); - evt.initMouseEvent("mousedown", true, true, view, 1, x + 1, y + 1, 0, 0, /*ctrl*/ new_tab, /*event.altKey*/0, /*event.shiftKey*/ new_window, /*event.metaKey*/ new_tab, 0, null); - elem.dispatchEvent(evt); - - var evt = doc.createEvent("MouseEvents"); - evt.initMouseEvent("click", true, true, view, 1, x + 1, y + 1, 0, 0, /*ctrl*/ new_tab, /*event.altKey*/0, /*event.shiftKey*/ new_window, /*event.metaKey*/ new_tab, 0, null); - elem.dispatchEvent(evt); - - // for 'pure' open calls without a new tab or window it doesn't - // make sense to open more hints in the current tab, open new tabs - // for it - if (!new_tab && !new_window) - new_tab = true; - } - - return 0; - }; - - this.yankUrlHints = function () - { - var loc = ""; - var elems = this.hintedElements(); - var tmp = ""; - for (var i = 0; i < elems.length; i++) - { - tmp = elems[i].refElem.href; - if (typeof(tmp) != "undefined" && tmp.length > 0) - { - if (i > 0) - loc += "\n"; - loc += tmp; - } - } - - // disable the hints before we can echo() an information - this.disableHahMode(null, true); - - vimperator.copyToClipboard(loc); - vimperator.echo("Yanked " + loc); - }; - - this.yankTextHints = function () - { - var loc = ""; - var elems = this.hintedElements(); - var tmp = ""; - for (var i = 0; i < elems.length; i++) - { - tmp = elems[i].refElem.textContent; - if (typeof(tmp) != "undefined" && tmp.length > 0) - { - if (i > 0) - loc += "\n"; - loc += tmp; - } - } - - // disable the hints before we can echo() an information - this.disableHahMode(null, true); - - vimperator.copyToClipboard(loc); - vimperator.echo("Yanked " + loc); - }; - - this.saveHints = function (skip_prompt) - { - var elems = this.hintedElements(); - - for (var i = 0; i < elems.length; i++) - { - var doc = elems[i].ownerDocument; - var url = makeURLAbsolute(elems[i].refElem.baseURI, elems[i].refElem.href); - var text = elems[i].refElem.textContent; - - try - { - urlSecurityCheck(url, doc.location.href); - saveURL(url, text, null, true, skip_prompt, makeURI(url, doc.characterSet)); - } - catch (e) - { - vimperator.echoerr(e); - } - } - } - - function setMouseOverElement(elem) - { - var doc = window.document; - var elemTagName = elem.localName.toLowerCase(); - - if (elemTagName == "frame" || elemTagName == "iframe") - { - elem.contentWindow.focus(); - return; - } - //else - //{ - // elem.focus(); - //} - - var evt = doc.createEvent("MouseEvents"); - var x = 0; - var y = 0; - // for imagemap - if (elemTagName == "area") - { - var coords = elem.getAttribute("coords").split(","); - x = Number(coords[0]); - y = Number(coords[1]); - } - - evt.initMouseEvent("mouseover", true, true, doc.defaultView, 1, x, y, 0, 0, 0, 0, 0, 0, 0, null); - elem.dispatchEvent(evt); - } - - //////////////////////////////////////////////////////////////////////////////// - // event handlers - //////////////////////////////////////////////////////////////////////////////// - - // returns nr. of fully parsed links when a new hint has been found, - // otherwise 0 if current state is part of a hint, or -1 if an error occured - // (like we have typed keys which never can become a hint - this.processEvent = function (event) - { - if (!isHahModeEnabled) - return -1; - - // reset state to show that we are in processing mode - state = 0; - - var num = String.fromCharCode(event.charCode).toUpperCase(); - var hintCharacters = vimperator.options["hintchars"]; - if (num != null && hintCharacters.toUpperCase().indexOf(num) > -1) - { - var oldLinkNumString = linkNumString; - linkNumString += "" + num; - // update reference to currently selected node; - var elem = getHintById(linkNumString); - changeHintFocus(linkNumString, oldLinkNumString); - - // if we found the hint, fine just return it - if (elem) - { - hintedElems.push(elem); - linkNumString = ""; - state = 1; - return hintedElems.length; - } - - //calculate how many characters a hint must have - var hintLength = 1; - var tmp = linkCount; - while ((tmp /= hintCharacters.length) > 1.0) - hintLength++; - - if (linkNumString.length >= hintLength) - return -1; - else - return 0; - } - // an unparseable or wrong key - return -1; - } - function genHintContainer(doc) { if (doc.getElementsByTagName("HINTS").length > 0) @@ -671,7 +373,7 @@ vimperator.Hints = function () //{{{ hints = doc.createElement("HINTS"); hints.id = "hah_hints"; - hints.valid_hint_count = 0; // initially 0 elements are usable as hints + hints.validHintCount = 0; // initially 0 elements are usable as hints if (doc.body) doc.body.appendChild(hints); @@ -706,16 +408,329 @@ vimperator.Hints = function () //{{{ linkNumString = ""; isHahModeEnabled = true; - setTimeout( function () { + setTimeout(function () { createHints(); showHints(null, 0); }, 100); } } + function setMouseOverElement(elem) + { + var doc = window.document; + var elemTagName = elem.localName.toLowerCase(); + + if (elemTagName == "frame" || elemTagName == "iframe") + { + elem.contentWindow.focus(); + return; + } + //else + //{ + // elem.focus(); + //} + + var evt = doc.createEvent("MouseEvents"); + var x = 0; + var y = 0; + // for imagemap + if (elemTagName == "area") + { + var coords = elem.getAttribute("coords").split(","); + x = Number(coords[0]); + y = Number(coords[1]); + } + + evt.initMouseEvent("mouseover", true, true, doc.defaultView, 1, x, y, 0, 0, 0, 0, 0, 0, 0, null); + elem.dispatchEvent(evt); + } + + /////////////////////////////////////////////////////////////////////////////}}} + ////////////////////// PUBLIC SECTION ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////{{{ + + var hintManager = { + + get hintedElements() { return hintedElems; }, + get currentState() { return state; }, + get setCurrentState(s) { state = s; }, + + loadCoord: function (winId, i) + { + win = wins[winId]; + + // win.res is not ready when loading has not finished yet + if (!win.res) + return; + + var elem = win.res.snapshotItem(i); + + if (elem) + genElemCoords(elem); + + i++; + + if (i < win.res.snapshotLength && !isHahModeEnabled) + window.setTimeout("vimperator.hints.loadCoord(" + winId + ", "+ i +");", 1); + else + win.coordLoaderId = null; + }, + + //////////////////////////////////////////////////////////////////////////////// + // basic functionality + //////////////////////////////////////////////////////////////////////////////// + + /** + * Enables the HaH-mode by showing the hints and prepare to input the + * hint numbers + * + * @author Pekka Sillanpaa + * @param event that caused the mode to change + * @return -1 if already enabled + */ + //function enableHahMode(event, mode) + enableHahMode: function (mode) + { + vimperator.setMode(vimperator.modes.HINTS, mode); + state = 0; + linkCount = 0; + linkNumString = ""; + isHahModeEnabled = true; + + createHints(); + showHints(null, 0); + + return true; + }, + + /** + * Disables the HaH-mode by hiding the hints and disabling the input mode + * + * @author Pekka Sillanpaa + * @param event that caused the mode to change + * @param action = true if something is to be clicked + * false if cancel + * @return -1 if already disabled + */ + //function disableHahMode(event) + disableHahMode: function (win) + { + if (!isHahModeEnabled) + return; + + vimperator.setMode(vimperator.modes.NORMAL); + isHahModeEnabled = false; + linkNumString = ""; + hintedElems = []; + + removeHints(win); + return 0; + }, + + resetHintedElements: function () + { + linkNumString = ""; + state = 0; + + while (hintedElems.length > 0) + { + var elem = hintedElems.pop(); + if (!elem) + return 0; + // reset style attribute + setHintStyle(elem, vimperator.options["hintstyle"]); + } + }, + + + reshowHints: function () + { + onResize(null); + + if (isHahModeEnabled) + { + removeHints(); + createHints(); + showHints(null, 0); + } + }, + + + // TODO: move these functions somewhere more general + + // this function 'click' an element, which also works + // for javascript links + openHints: function (newTab, newWindow) + { + var x = 0, y = 0; + + while (hintedElems.length > 0) + { + var elem = hintedElems.pop(); + if (!elem) + return 0; + + setHintStyle(elem, vimperator.options["hintstyle"]); + elem = elem.refElem; + var elemTagName = elem.localName.toLowerCase(); + elem.focus(); + + if (elemTagName == "frame" || elemTagName == "iframe") + return 0; + + // for imagemap + if (elemTagName == "area") + { + var coords = elem.getAttribute("coords").split(","); + x = Number(coords[0]); + y = Number(coords[1]); + } + var doc = window.content.document; + var view = window.document.defaultView; + + var evt = doc.createEvent("MouseEvents"); + evt.initMouseEvent("mousedown", true, true, view, 1, x + 1, y + 1, 0, 0, /*ctrl*/ newTab, /*event.altKey*/0, /*event.shiftKey*/ newWindow, /*event.metaKey*/ newTab, 0, null); + elem.dispatchEvent(evt); + + var evt = doc.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, view, 1, x + 1, y + 1, 0, 0, /*ctrl*/ newTab, /*event.altKey*/0, /*event.shiftKey*/ newWindow, /*event.metaKey*/ newTab, 0, null); + elem.dispatchEvent(evt); + + // for 'pure' open calls without a new tab or window it doesn't + // make sense to open more hints in the current tab, open new tabs + // for it + if (!newTab && !newWindow) + newTab = true; + } + + return 0; + }, + + yankUrlHints: function () + { + var loc = ""; + var elems = this.hintedElements(); + var tmp = ""; + for (var i = 0; i < elems.length; i++) + { + tmp = elems[i].refElem.href; + if (typeof tmp != "undefined" && tmp.length > 0) + { + if (i > 0) + loc += "\n"; + loc += tmp; + } + } + + // disable the hints before we can echo() an information + this.disableHahMode(null, true); + + vimperator.copyToClipboard(loc); + vimperator.echo("Yanked " + loc); + }, + + yankTextHints: function () + { + var loc = ""; + var elems = this.hintedElements(); + var tmp = ""; + for (var i = 0; i < elems.length; i++) + { + tmp = elems[i].refElem.textContent; + if (typeof tmp != "undefined" && tmp.length > 0) + { + if (i > 0) + loc += "\n"; + loc += tmp; + } + } + + // disable the hints before we can echo() an information + this.disableHahMode(null, true); + + vimperator.copyToClipboard(loc); + vimperator.echo("Yanked " + loc); + }, + + saveHints: function (skipPrompt) + { + var elems = this.hintedElements(); + + for (var i = 0; i < elems.length; i++) + { + var doc = elems[i].ownerDocument; + var url = makeURLAbsolute(elems[i].refElem.baseURI, elems[i].refElem.href); + var text = elems[i].refElem.textContent; + + try + { + urlSecurityCheck(url, doc.location.href); + saveURL(url, text, null, true, skipPrompt, makeURI(url, doc.characterSet)); + } + catch (e) + { + vimperator.echoerr(e); + } + } + }, + + //////////////////////////////////////////////////////////////////////////////// + // event handlers + //////////////////////////////////////////////////////////////////////////////// + + // returns nr. of fully parsed links when a new hint has been found, + // otherwise 0 if current state is part of a hint, or -1 if an error occured + // (like we have typed keys which never can become a hint + processEvent: function (event) + { + if (!isHahModeEnabled) + return -1; + + // reset state to show that we are in processing mode + state = 0; + + var num = String.fromCharCode(event.charCode).toUpperCase(); + var hintCharacters = vimperator.options["hintchars"]; + if (num != null && hintCharacters.toUpperCase().indexOf(num) > -1) + { + var oldLinkNumString = linkNumString; + linkNumString += "" + num; + // update reference to currently selected node; + var elem = getHintById(linkNumString); + changeHintFocus(linkNumString, oldLinkNumString); + + // if we found the hint, fine just return it + if (elem) + { + hintedElems.push(elem); + linkNumString = ""; + state = 1; + return hintedElems.length; + } + + //calculate how many characters a hint must have + var hintLength = 1; + var tmp = linkCount; + while ((tmp /= hintCharacters.length) > 1.0) + hintLength++; + + if (linkNumString.length >= hintLength) + return -1; + else + return 0; + } + // an unparseable or wrong key + return -1; + } + + }; + window.document.addEventListener("DOMContentLoaded", initDoc, null); // FIXME: add resize support //window.addEventListener("resize", onResize, null); -} //}}} + + return hintManager; + //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/io.js b/content/io.js index 3c641a74..fa6462f0 100644 --- a/content/io.js +++ b/content/io.js @@ -27,9 +27,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.IO = function () +vimperator.IO = function () //{{{ { - var environment_service = Components.classes["@mozilla.org/process/environment;1"] + var environmentService = Components.classes["@mozilla.org/process/environment;1"] .getService(Components.interfaces.nsIEnvironment); return { @@ -54,30 +54,30 @@ vimperator.IO = function () // expand "~" to VIMPERATOR_HOME or HOME (USERPROFILE or HOMEDRIVE\HOMEPATH on Windows if HOME is not set) if (/^~/.test(path)) { - var home = environment_service.get("VIMPERATOR_HOME"); + var home = environmentService.get("VIMPERATOR_HOME"); if (!home) - home = environment_service.get("HOME"); + home = environmentService.get("HOME"); if (WINDOWS && !home) - home = environment_service.get("USERPROFILE") || - environment_service.get("HOMEDRIVE") + environment_service.get("HOMEPATH"); + home = environmentService.get("USERPROFILE") || + environmentService.get("HOMEDRIVE") + environmentService.get("HOMEPATH"); path = path.replace("~", home); } // expand any $ENV vars - var env_vars = path.match(/\$\w+\b/g); // this is naive but so is Vim and we like to be compatible + var envVars = path.match(/\$\w+\b/g); // this is naive but so is Vim and we like to be compatible - if (env_vars) + if (envVars) { var expansion; - for (var i = 0; i < env_vars.length; i++) + for (var i = 0; i < envVars.length; i++) { - expansion = environment_service.get(env_vars[i].replace("$", "")); + expansion = environmentService.get(envVars[i].replace("$", "")); if (expansion) - path = path.replace(env_vars[i], expansion); + path = path.replace(envVars[i], expansion); } } @@ -86,30 +86,30 @@ vimperator.IO = function () getPluginDir: function () { - var plugin_dir; + var pluginDir; if (navigator.platform == "Win32") - plugin_dir = "~/vimperator/plugin"; + pluginDir = "~/vimperator/plugin"; else - plugin_dir = "~/.vimperator/plugin"; + pluginDir = "~/.vimperator/plugin"; - plugin_dir = this.getFile(this.expandPath(plugin_dir)); + pluginDir = this.getFile(this.expandPath(pluginDir)); - return plugin_dir.exists() && plugin_dir.isDirectory() ? plugin_dir : null; + return pluginDir.exists() && pluginDir.isDirectory() ? pluginDir : null; }, getRCFile: function () { - var rc_file1 = this.getFile(this.expandPath("~/.vimperatorrc")); - var rc_file2 = this.getFile(this.expandPath("~/_vimperatorrc")); + var rcFile1 = this.getFile(this.expandPath("~/.vimperatorrc")); + var rcFile2 = this.getFile(this.expandPath("~/_vimperatorrc")); if (navigator.platform == "Win32") - [rc_file1, rc_file2] = [rc_file2, rc_file1] + [rcFile1, rcFile2] = [rcFile2, rcFile1] - if (rc_file1.exists() && rc_file1.isFile()) - return rc_file1; - else if (rc_file2.exists() && rc_file2.isFile()) - return rc_file2; + if (rcFile1.exists() && rcFile1.isFile()) + return rcFile1; + else if (rcFile2.exists() && rcFile2.isFile()) + return rcFile2; else return null; }, @@ -133,12 +133,12 @@ vimperator.IO = function () createInstance(Components.interfaces.nsILocalFile); if (navigator.platform == "Win32") { - var dir = environment_service.get("TMP") || environment_service.get("TEMP") || "C:\\"; + var dir = environmentService.get("TMP") || environmentService.get("TEMP") || "C:\\"; file.initWithPath(dir + "\\vimperator.tmp"); } else { - var dir = environment_service.get("TMP") || environment_service.get("TEMP") || "/tmp/"; + var dir = environmentService.get("TMP") || environmentService.get("TEMP") || "/tmp/"; file.initWithPath(dir + "/vimperator.tmp"); } @@ -234,7 +234,7 @@ vimperator.IO = function () ocstream.close(); ofstream.close(); } - } -} + }; +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/mappings.js b/content/mappings.js index d46f4bce..aac00a20 100644 --- a/content/mappings.js +++ b/content/mappings.js @@ -26,7 +26,7 @@ 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.Map = function (mode, cmds, action, extra_info) //{{{ +vimperator.Map = function (mode, cmds, action, extraInfo) //{{{ { if (!mode || (!cmds || !cmds.length) || !action) return null; @@ -37,12 +37,12 @@ vimperator.Map = function (mode, cmds, action, extra_info) //{{{ this.usage = [this.names[0]]; - if (extra_info) + if (extraInfo) { - this.flags = extra_info.flags || 0; + this.flags = extraInfo.flags || 0; - if (extra_info.usage) - this.usage = extra_info.usage; + if (extraInfo.usage) + this.usage = extraInfo.usage; else { this.usage = this.names[0]; // only the first command name @@ -53,17 +53,17 @@ vimperator.Map = function (mode, cmds, action, extra_info) //{{{ this.usage = [this.usage]; // FIXME: usage an array - needed for the help } - this.help = extra_info.help || null; - this.short_help = extra_info.short_help || null; + this.help = extraInfo.help || null; + this.shortHelp = extraInfo.shortHelp || null; - this.rhs = extra_info.rhs || null; + this.rhs = extraInfo.rhs || null; // TODO: are these limited to HINTS mode? // Only set for hints maps - this.cancel_mode = extra_info.cancel_mode || false; - this.always_active = extra_info.always_active || false; + this.cancelMode = extraInfo.cancelMode || false; + this.alwaysActive = extraInfo.alwaysActive || false; } -} +}; vimperator.Map.prototype.hasName = function (name) { @@ -74,7 +74,7 @@ vimperator.Map.prototype.hasName = function (name) } return false; -} +}; // Since we will add many Map-objects, we add some functions as prototypes // this will ensure we only have one copy of each function, not one for each object @@ -88,7 +88,7 @@ vimperator.Map.prototype.execute = function (motion, count, argument) if (this.flags & vimperator.Mappings.flags.ARGUMENT) args.push(argument); this.action.apply(this, args); -} +}; //}}} vimperator.Mappings = function () //{{{ @@ -177,123 +177,127 @@ vimperator.Mappings = function () //{{{ ARGUMENT: 1 << 2 }; - // NOTE: just normal mode for now - this.__iterator__ = function () - { - return mappingsIterator(vimperator.modes.NORMAL, main); - } + var mappingManager = { - // FIXME - this.getIterator = function (mode) - { - return mappingsIterator(mode, main); - } - - // FIXME - this.getUserIterator = function (mode) - { - return mappingsIterator(mode, user); - } - - this.hasMap = function (mode, cmd) - { - var user_maps = user[mode]; - - for (var i = 0; i < user_maps.length; i++) + // NOTE: just normal mode for now + __iterator__: function () { - if (user_maps[i].names.indexOf(cmd) != -1) - return true; - } + return mappingsIterator(vimperator.modes.NORMAL, main); + }, - return false; - } - - this.add = function (map) - { - for (var i = 0; i < map.names.length; i++) + // FIXME + getIterator: function (mode) { - // only store keysyms with uppercase modifier strings - map.names[i] = map.names[i].replace(/[casm]-/g, function ($0) { return $0.toUpperCase(); }); - removeMap(map.mode, map.names[i]); - } + return mappingsIterator(mode, main); + }, - user[map.mode].push(map); - } - - this.remove = function (mode, cmd) - { - removeMap(mode, cmd); - } - - this.removeAll = function (mode) - { - user[mode] = []; - } - - this.get = function (mode, cmd) - { - var map = getMap(mode, cmd, user); - - if (!map) - map = getMap(mode, cmd, main); - - return map; - } - - // TODO: move default maps to their own v.normal namespace - this.getDefaultMap = function (mode, cmd) - { - return getMap(mode, cmd, main); - } - - // returns an array of mappings with names which start with "cmd" - this.getCandidates = function (mode, cmd) - { - var mappings = []; - var matches = []; - - mappings = user[mode].concat(main[mode]); - - for (var i = 0; i < mappings.length; i++) + // FIXME + getUserIterator: function (mode) { - var map = mappings[i]; - for (var j = 0; j < map.names.length; j++) + return mappingsIterator(mode, user); + }, + + hasMap: function (mode, cmd) + { + var userMaps = user[mode]; + + for (var i = 0; i < userMaps.length; i++) { - if (map.names[j].indexOf(cmd) == 0) - matches.push(map); + if (userMaps[i].names.indexOf(cmd) != -1) + return true; } - } - return matches; - } + return false; + }, - // TODO: implement filtering - this.list = function (mode, filter) - { - var maps = user[mode]; - - if (!maps || maps.length == 0) + add: function (map) { - vimperator.echo("No mappings found"); - return; - } - - var list = ""; - for (var i = 0; i < maps.length; i++) - { - for (var j = 0; j < maps[i].names.length; j++) + for (var i = 0; i < map.names.length; i++) { - list += ""; - list += ""; - if (maps[i].rhs) - list += "" - list += ""; + // only store keysyms with uppercase modifier strings + map.names[i] = map.names[i].replace(/[casm]-/g, function ($0) { return $0.toUpperCase(); }); + removeMap(map.mode, map.names[i]); } - } - list += "
    " + vimperator.util.escapeHTML(maps[i].names[j]) + " " + vimperator.util.escapeHTML(maps[i].rhs) + "
    "; - vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); - } + user[map.mode].push(map); + }, + + remove: function (mode, cmd) + { + removeMap(mode, cmd); + }, + + removeAll: function (mode) + { + user[mode] = []; + }, + + get: function (mode, cmd) + { + var map = getMap(mode, cmd, user); + + if (!map) + map = getMap(mode, cmd, main); + + return map; + }, + + // TODO: move default maps to their own v.normal namespace + getDefaultMap: function (mode, cmd) + { + return getMap(mode, cmd, main); + }, + + // returns an array of mappings with names which start with "cmd" + getCandidates: function (mode, cmd) + { + var mappings = []; + var matches = []; + + mappings = user[mode].concat(main[mode]); + + for (var i = 0; i < mappings.length; i++) + { + var map = mappings[i]; + for (var j = 0; j < map.names.length; j++) + { + if (map.names[j].indexOf(cmd) == 0) + matches.push(map); + } + } + + return matches; + }, + + // TODO: implement filtering + list: function (mode, filter) + { + var maps = user[mode]; + + if (!maps || maps.length == 0) + { + vimperator.echo("No mappings found"); + return; + } + + var list = ""; + for (var i = 0; i < maps.length; i++) + { + for (var j = 0; j < maps[i].names.length; j++) + { + list += ""; + list += ""; + if (maps[i].rhs) + list += ""; + list += ""; + } + } + list += "
    " + vimperator.util.escapeHTML(maps[i].names[j]) + " " + vimperator.util.escapeHTML(maps[i].rhs) + "
    "; + + vimperator.commandline.echo(list, vimperator.commandline.HL_NORMAL, vimperator.commandline.FORCE_MULTILINE); + } + + }; /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// DEFAULT MAPPINGS //////////////////////////////////////// @@ -306,21 +310,21 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [""], function () { vimperator.help(null); }, { - short_help: "Open help window", + shortHelp: "Open help window", help: "The default section is shown, if you need help for a specific topic, try :help <F1>." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [":"], function () { vimperator.commandline.open(":", "", vimperator.modes.EX); }, { - short_help: "Start command line mode", + shortHelp: "Start command line mode", help: "In command line mode, you can perform extended commands, which may require arguments." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["I"], function () { vimperator.addMode(null, vimperator.modes.ESCAPE_ALL_KEYS); }, { - short_help: "Disable Vimperator keys", + shortHelp: "Disable Vimperator keys", help: "Starts an 'ignorekeys' mode, where all keys except <Esc> are passed to the next event handler.
    " + "This is especially useful, if JavaScript controlled forms like the RichEdit form fields of GMail don't work anymore.
    " + "To exit this mode, press <Esc>. If you also need to pass <Esc>" + @@ -330,7 +334,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [""], function () { vimperator.addMode(null, vimperator.modes.ESCAPE_ONE_KEY); }, { - short_help: "Escape next key", + shortHelp: "Escape next key", help: "If you need to pass a certain key to a JavaScript form field or another extension prefix the key with <C-v>.
    " + "Also works to unshadow Firefox shortcuts like <C-o> which are otherwise hidden in Vimperator.
    " + "When in 'ignorekeys' mode (activated by <I>), <C-v> will pass the next key to Vimperator instead of the web page." @@ -339,14 +343,14 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [""], BrowserStop, { - short_help: "Stop loading", + shortHelp: "Stop loading", help: "Stops loading the current web page." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [""], function () { return; }, { - short_help: "Do nothing", + shortHelp: "Do nothing", help: "This command is useful for disabling a specific mapping. " + ":map <C-n> <Nop> will prevent <C-n> from doing anything." } @@ -354,7 +358,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["", ""], vimperator.events.onEscape, { - short_help: "Focus content", + shortHelp: "Focus content", help: "Exits any command line or hint mode and returns to browser mode.
    " + "Also focuses the web page, in case a form field has focus and eats our key presses." } @@ -363,7 +367,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["]f"], function (count) { vimperator.buffer.shiftFrameFocus(count > 1 ? count : 1, true); }, { - short_help: "Focus next frame", + shortHelp: "Focus next frame", help: "Transfers keyboard focus to the [count]th next frame in order. The newly focused frame is briefly colored red. Does not wrap.", flags: vimperator.Mappings.flags.COUNT } @@ -371,7 +375,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["[f"], function (count) { vimperator.buffer.shiftFrameFocus(count > 1 ? count : 1, false); }, { - short_help: "Focus previous frame", + shortHelp: "Focus previous frame", help: "Transfers keyboard focus to the [count]th previous frame in order. The newly focused frame is briefly colored red. Does not wrap.", flags: vimperator.Mappings.flags.COUNT } @@ -379,14 +383,14 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["b"], function () { vimperator.commandline.open(":", "buffer! ", vimperator.modes.EX); }, { - short_help: "Open a prompt to switch buffers", + shortHelp: "Open a prompt to switch buffers", help: "Typing the corresponding number switches to this buffer." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["B"], function () { vimperator.buffer.list(true); }, { - short_help: "Toggle buffer list", + shortHelp: "Toggle buffer list", help: "Toggles the display of the buffer list which shows all opened tabs.
    " + "WARNING: This mapping may be removed/changed in future." } @@ -394,7 +398,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["gb"], function (count) { vimperator.buffer.switchTo(null, null, count, false); }, { - short_help: "Repeat last :buffer[!] command", + shortHelp: "Repeat last :buffer[!] command", help: "This is useful to quickly jump between buffers which have a similar URL or title.", flags: vimperator.Mappings.flags.COUNT } @@ -402,7 +406,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["gB"], function (count) { vimperator.buffer.switchTo(null, null, count, true); }, { - short_help: "Repeat last :buffer[!] command in reverse direction", + shortHelp: "Repeat last :buffer[!] command in reverse direction", help: "Just like gb but in the other direction.", flags: vimperator.Mappings.flags.COUNT } @@ -410,7 +414,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["d"], function (count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, false, 0); }, { - short_help: "Delete current buffer (=tab)", + shortHelp: "Delete current buffer (=tab)", help: "Count is supported, 2d removes the current and next tab and the one to the right is selected. " + "Does not wrap if [count] is larger than available tabs to the right.", flags: vimperator.Mappings.flags.COUNT @@ -419,7 +423,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["D"], function (count) { vimperator.tabs.remove(getBrowser().mCurrentTab, count, true, 0); }, { - short_help: "Delete current buffer (=tab)", + shortHelp: "Delete current buffer (=tab)", help: "Count is supported, 2D removes the current and previous tab and the one to the left is selected. " + "Does not wrap if [count] is larger than available tabs to the left.", flags: vimperator.Mappings.flags.COUNT @@ -428,7 +432,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["gh"], BrowserHome, { - short_help: "Go home", + shortHelp: "Go home", help: "Opens the homepage in the current tab." } )); @@ -440,7 +444,7 @@ vimperator.Mappings = function () //{{{ vimperator.NEW_TAB : vimperator.NEW_BACKGROUND_TAB); }, { - short_help: "Go home in a new tab", + shortHelp: "Go home in a new tab", help: "Opens the homepage in a new tab. " + "Whether the new tab is activated or not depends on the 'activate' option.
    " } @@ -448,7 +452,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["go"], function (arg) { vimperator.quickmarks.jumpTo(arg, vimperator.CURRENT_TAB); }, { - short_help: "Jump to a QuickMark in the current tab", + shortHelp: "Jump to a QuickMark in the current tab", usage: ["go{a-zA-Z0-9}"], help: "Open any QuickMark in the current tab. You can mark any URLs with M{a-zA-Z0-9}. " + "These QuickMarks are persistent across browser sessions.", @@ -463,7 +467,7 @@ vimperator.Mappings = function () //{{{ vimperator.NEW_TAB : vimperator.NEW_BACKGROUND_TAB); }, { - short_help: "Jump to a QuickMark in a new tab", + shortHelp: "Jump to a QuickMark in a new tab", usage: ["gn{a-zA-Z0-9}"], help: "Works like go{a-zA-Z0-9} but opens the QuickMark in a new tab. " + "Whether the new tab is activated or not depends on the 'activate' option.
    " + @@ -479,14 +483,14 @@ vimperator.Mappings = function () //{{{ vimperator.NEW_BACKGROUND_TAB : vimperator.NEW_TAB); }, { - short_help: "Open (put) a URL based on the current clipboard contents in a new buffer", + shortHelp: "Open (put) a URL based on the current clipboard contents in a new buffer", help: "Works like P, but inverts the 'activate' option." } )); addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["gt", "", "", ""], function (count) { vimperator.tabs.select(count > 0 ? count - 1: "+1", count > 0 ? false : true); }, { - short_help: "Go to the next tab", + shortHelp: "Go to the next tab", help: "Cycles to the first tab, when the last is selected.
    Count is supported: 3gt goes to the third tab.", flags: vimperator.Mappings.flags.COUNT } @@ -494,7 +498,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["gT", "", "", ""], function (count) { vimperator.tabs.select("-" + (count < 1 ? 1 : count), true); }, { - short_help: "Go {count} pages back", + shortHelp: "Go {count} pages back", help: "Wraps around from the first tab to the last tab.
    Count is supported: 3gT goes three tabs back.", flags: vimperator.Mappings.flags.COUNT } @@ -521,7 +525,7 @@ vimperator.Mappings = function () //{{{ vimperator.tabs.select(index); }, { - short_help: "Select the alternate tab", + shortHelp: "Select the alternate tab", usage: [""], help: "The alternate tab is the last selected tab. This provides a quick method of toggling between two tabs." } @@ -538,7 +542,7 @@ vimperator.Mappings = function () //{{{ vimperator.marks.add(arg); }, { - short_help: "Set mark at the cursor position", + shortHelp: "Set mark at the cursor position", usage: ["m{a-zA-Z}"], help: "Marks a-z are local to the buffer, whereas A-Z are valid between buffers.", flags: vimperator.Mappings.flags.ARGUMENT @@ -547,7 +551,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["'", "`"], function (arg) { vimperator.marks.jumpTo(arg); }, { - short_help: "Jump to the mark in the current buffer", + shortHelp: "Jump to the mark in the current buffer", usage: ["'{a-zA-Z}"], help: "Marks a-z are local to the buffer, whereas A-Z are valid between buffers.", flags: vimperator.Mappings.flags.ARGUMENT @@ -565,7 +569,7 @@ vimperator.Mappings = function () //{{{ vimperator.quickmarks.add(arg, vimperator.buffer.URL); }, { - short_help: "Add new QuickMark for current URL", + shortHelp: "Add new QuickMark for current URL", usage: ["M{a-zA-Z0-9}"], help: "You can go to a marked URL in the current tab with go{a-zA-Z0-9} or in a new tab with gn{a-zA-Z0-9}. " + "These QuickMarks are persistent across browser sessions.", @@ -575,21 +579,21 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["o"], function () { vimperator.commandline.open(":", "open ", vimperator.modes.EX); }, { - short_help: "Open one or more URLs in the current tab", + shortHelp: "Open one or more URLs in the current tab", help: "See :open for more details." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["O"], function () { vimperator.commandline.open(":", "open " + vimperator.buffer.URL, vimperator.modes.EX); }, { - short_help: "Open one or more URLs in the current tab, based on current location", + shortHelp: "Open one or more URLs in the current tab, based on current location", help: "Works like o, but preselects current URL in the :open query." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["p", ""], function () { vimperator.open(readFromClipboard()); }, { - short_help: "Open (put) a URL based on the current clipboard contents in the current buffer", + shortHelp: "Open (put) a URL based on the current clipboard contents in the current buffer", help: "You can also just select (for non-X11 users: copy) some non-URL text, and search for it with the default search engine or keyword (specified by the 'defsearch' option) with p." } )); @@ -601,7 +605,7 @@ vimperator.Mappings = function () //{{{ vimperator.NEW_TAB : vimperator.NEW_BACKGROUND_TAB); }, { - short_help: "Open (put) a URL based on the current clipboard contents in a new buffer", + shortHelp: "Open (put) a URL based on the current clipboard contents in a new buffer", help: "Works like p, but opens a new tab.
    " + "Whether the new buffer is activated, depends on the 'activate' option." } @@ -609,21 +613,21 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["r"], function () { vimperator.tabs.reload(getBrowser().mCurrentTab, false); }, { - short_help: "Reload", + shortHelp: "Reload", help: "Forces reloading of the current page." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["R"], function () { vimperator.tabs.reload(getBrowser().mCurrentTab, true); }, { - short_help: "Reload while skipping the cache", + shortHelp: "Reload while skipping the cache", help: "Forces reloading of the current page skipping the cache." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["t"], function () { vimperator.commandline.open(":", "tabopen ", vimperator.modes.EX); }, { - short_help: "Open one or more URLs in a new tab", + shortHelp: "Open one or more URLs in a new tab", help: "Like o but open URLs in a new tab.
    " + "See :tabopen for more details." } @@ -631,14 +635,14 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["T"], function () { vimperator.commandline.open(":", "tabopen " + vimperator.buffer.URL, vimperator.modes.EX); }, { - short_help: "Open one or more URLs in a new tab, based on current location", + shortHelp: "Open one or more URLs in a new tab, based on current location", help: "Works like t, but preselects current URL in the :tabopen query." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["u"], function (count) { vimperator.commands.undo("", false, count); }, { - short_help: "Undo closing of a tab", + shortHelp: "Undo closing of a tab", help: "If a count is given, don't close the last but the [count]th last tab.", flags: vimperator.Mappings.flags.COUNT } @@ -651,7 +655,7 @@ vimperator.Mappings = function () //{{{ vimperator.echo("Yanked " + url); }, { - short_help: "Yank current location to the clipboard", + shortHelp: "Yank current location to the clipboard", help: "When running in X11 the location is also put into the selection, which can be pasted with the middle mouse button." } )); @@ -662,42 +666,42 @@ vimperator.Mappings = function () //{{{ vimperator.copyToClipboard(sel); }, { - short_help: "Copy selected text", + shortHelp: "Copy selected text", help: "The currently selected text is copied to the system clipboard." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["zi", "+"], function (count) { vimperator.buffer.zoomIn(count > 1 ? count : 1); }, { - short_help: "Zoom in current web page by 25%", + shortHelp: "Zoom in current web page by 25%", flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["zI"], function (count) { vimperator.buffer.zoomIn((count > 1 ? count : 1) * 4); }, { - short_help: "Zoom in current web page by 100%", + shortHelp: "Zoom in current web page by 100%", flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["zo", "-"], function (count) { vimperator.buffer.zoomOut(count > 1 ? count : 1); }, { - short_help: "Zoom out current web page by 25%", + shortHelp: "Zoom out current web page by 25%", flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["zO"], function (count) { vimperator.buffer.zoomOut((count > 1 ? count : 1) * 4); }, { - short_help: "Zoom out current web page by 100%", + shortHelp: "Zoom out current web page by 100%", flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["zz"], function (count) { vimperator.buffer.textZoom = count > 1 ? count : 100; }, { - short_help: "Set zoom value of the web page", + shortHelp: "Set zoom value of the web page", help: "Zoom value can be between 1 and 2000%. If it is omitted, zoom is reset to 100%.", flags: vimperator.Mappings.flags.COUNT } @@ -705,14 +709,14 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["ZQ"], function () { vimperator.quit(false); }, { - short_help: "Quit and don't save the session", + shortHelp: "Quit and don't save the session", help: "Works like :qall." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["ZZ"], function () { vimperator.quit(true); }, { - short_help: "Quit and save the session", + shortHelp: "Quit and save the session", help: "Quit Vimperator, no matter how many tabs/windows are open. The session is stored.
    " + "Works like :xall." } @@ -722,20 +726,20 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["0", "^"], function () { vimperator.buffer.scrollStart(); }, { - short_help: "Scroll to the absolute left of the document", + shortHelp: "Scroll to the absolute left of the document", help: "Unlike in Vim, 0 and ^ work exactly the same way." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["$"], function () { vimperator.buffer.scrollEnd(); }, { - short_help: "Scroll to the absolute right of the document" + shortHelp: "Scroll to the absolute right of the document" } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["gg", ""], function (count) { vimperator.buffer.scrollToPercentile(count > 0 ? count : 0); }, { - short_help: "Goto the top of the document", + shortHelp: "Goto the top of the document", help: "When used with [count] like in 35gg, it scrolls to 35% of the document.", flags: vimperator.Mappings.flags.COUNT } @@ -743,7 +747,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["G", ""], function (count) { vimperator.buffer.scrollToPercentile(count >= 0 ? count : 100); }, { - short_help: "Goto the end of the document", + shortHelp: "Goto the end of the document", help: "When used with [count] like in 35G, it scrolls to 35% of the document.", flags: vimperator.Mappings.flags.COUNT } @@ -751,7 +755,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["h", ""], function (count) { vimperator.buffer.scrollColumns(-(count > 1 ? count : 1)); }, { - short_help: "Scroll document to the left", + shortHelp: "Scroll document to the left", help: "Count is supported: 10h will move 10 times as much to the left.
    " + "If the document cannot scroll more, a beep is emitted (unless 'visualbell' is set).", flags: vimperator.Mappings.flags.COUNT @@ -760,7 +764,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["j", "", ""], function (count) { vimperator.buffer.scrollLines(count > 1 ? count : 1); }, { - short_help: "Scroll document down", + shortHelp: "Scroll document down", help: "Count is supported: 10j will move 10 times as much down.
    " + "If the document cannot scroll more, a beep is emitted (unless 'visualbell' is set).", flags: vimperator.Mappings.flags.COUNT @@ -769,7 +773,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["k", "", ""], function (count) { vimperator.buffer.scrollLines(-(count > 1 ? count : 1)); }, { - short_help: "Scroll document up", + shortHelp: "Scroll document up", help: "Count is supported: 10k will move 10 times as much up.
    " + "If the document cannot scroll more, a beep is emitted (unless 'visualbell' is set).", flags: vimperator.Mappings.flags.COUNT @@ -794,7 +798,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [""], function (count) { scrollByScrollSize(count, 1); }, { - short_help: "Scroll window downwards in the buffer", + shortHelp: "Scroll window downwards in the buffer", help: "The number of lines is set by the 'scroll' option which defaults to half a page. " + "If [count] is given 'scroll' is first set to this value.", flags: vimperator.Mappings.flags.COUNT @@ -803,7 +807,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [""], function (count) { scrollByScrollSize(count, -1); }, { - short_help: "Scroll window upwards in the buffer", + shortHelp: "Scroll window upwards in the buffer", help: "The number of lines is set by the 'scroll' option which defaults to half a page. " + "If [count] is given 'scroll' is first set to this value.", flags: vimperator.Mappings.flags.COUNT @@ -812,7 +816,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["l", ""], function (count) { vimperator.buffer.scrollColumns(count > 1 ? count : 1); }, { - short_help: "Scroll document to the right", + shortHelp: "Scroll document to the right", help: "Count is supported: 10l will move 10 times as much to the right.
    " + "If the document cannot scroll more, a beep is emitted (unless 'visualbell' is set).", flags: vimperator.Mappings.flags.COUNT @@ -821,7 +825,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["", "", ""], function (count) { vimperator.buffer.scrollPages(-(count > 1 ? count : 1)); }, { - short_help: "Scroll up a full page", + shortHelp: "Scroll up a full page", help: "Scroll window [count] pages Backwards (upwards) in the buffer.", flags: vimperator.Mappings.flags.COUNT } @@ -829,7 +833,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["", "", ""], function (count) { vimperator.buffer.scrollPages(count > 1 ? count : 1); }, { - short_help: "Scroll down a full page", + shortHelp: "Scroll down a full page", help: "Scroll window [count] pages Forwards (downwards) in the buffer.", flags: vimperator.Mappings.flags.COUNT } @@ -839,7 +843,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], [""], function (count) { vimperator.buffer.pageInfo(false); }, { - short_help: "Print the current file name", + shortHelp: "Print the current file name", help: "Also shows some additional file information like file size or the last modified date. " + "If {count} is given print the current file name with full path.", flags: vimperator.Mappings.flags.COUNT @@ -848,7 +852,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["g"], function (count) { vimperator.buffer.pageInfo(true); }, { - short_help: "Print file information", + shortHelp: "Print file information", help: "Same as :pa[geinfo]." } )); @@ -858,7 +862,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [""], function (count) { vimperator.history.stepTo(-(count > 1 ? count : 1)); }, { - short_help: "Go to an older position in the jump list", + shortHelp: "Go to an older position in the jump list", help: "The jump list is just the browser history for now.", flags: vimperator.Mappings.flags.COUNT } @@ -866,7 +870,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [""], function (count) { vimperator.history.stepTo(count > 1 ? count : 1); }, { - short_help: "Go to a newer position in the jump list", + shortHelp: "Go to a newer position in the jump list", help: "The jump list is just the browser history for now.", flags: vimperator.Mappings.flags.COUNT } @@ -874,7 +878,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["H", "", ""], function (count) { vimperator.history.stepTo(-(count > 1 ? count : 1)); }, { - short_help: "Go back in the browser history", + shortHelp: "Go back in the browser history", help: "Count is supported: 3H goes back 3 steps.", flags: vimperator.Mappings.flags.COUNT } @@ -882,7 +886,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["L", "", ""], function (count) { vimperator.history.stepTo(count > 1 ? count : 1); }, { - short_help: "Go forward in the browser history", + shortHelp: "Go forward in the browser history", help: "Count is supported: 3L goes forward 3 steps.", flags: vimperator.Mappings.flags.COUNT } @@ -922,7 +926,7 @@ vimperator.Mappings = function () //{{{ vimperator.open(gocmd); }, { - short_help: "Go to parent directory", + shortHelp: "Go to parent directory", help: "Count is supported: 2gu on http://www.example.com/dir1/dir2/file.htm would open http://www.example.com/dir1/.", flags: vimperator.Mappings.flags.COUNT } @@ -930,7 +934,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["gU", ""], function () { vimperator.open("..."); }, { - short_help: "Go to the root of the website", + shortHelp: "Go to the root of the website", help: "gU on http://www.example.com/dir1/dir2/file.htm opens http://www.example.com/.
    " + "When browsing a local directory, it goes to the root document." } @@ -940,7 +944,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["f"], function () { vimperator.hints.enableHahMode(vimperator.modes.QUICK_HINT); }, { - short_help: "Start QuickHint mode", + shortHelp: "Start QuickHint mode", help: "In QuickHint mode, every hintable item (according to the 'hinttags' XPath query) is assigned a label.
    " + "If you then press the keys for a label, it is followed as soon as it can be uniquely identified and this mode is stopped. Or press <Esc> to stop this mode.
    " + "If you write the hint in ALLCAPS, the hint is followed in a background tab." @@ -949,7 +953,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["F"], function () { vimperator.hints.enableHahMode(vimperator.modes.ALWAYS_HINT); }, { - short_help: "Start AlwaysHint mode", + shortHelp: "Start AlwaysHint mode", help: "In AlwaysHint mode, every hintable item (according to the 'hinttags' XPath query) is assigned a label.
    " + "If you then press the keys for a label, it is followed as soon as it can be uniquely identified. Labels stay active after following a hint in this mode, press <Esc> to stop this mode.
    " + "This hint mode is especially useful for browsing large sites like Forums as hints are automatically regenerated when switching to a new document.
    " + @@ -959,7 +963,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, [";"], function () { vimperator.hints.enableHahMode(vimperator.modes.EXTENDED_HINT); }, { - short_help: "Start ExtendedHint mode", + shortHelp: "Start ExtendedHint mode", help: "ExtendedHint mode is useful, since in this mode you can yank link locations, or open them in a new window.
    " + "E.g., if you want to yank the location of hint AB, press ; to start this hint mode.
    " + "Then press AB to select the hint. Now press y to yank its location.
    " + @@ -984,7 +988,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["/"], function () { vimperator.search.openSearchDialog(vimperator.modes.SEARCH_FORWARD); }, { - short_help: "Search forward for a pattern", + shortHelp: "Search forward for a pattern", usage: ["/{pattern}[/]"], help: "Search forward for the first occurrence of {pattern}.
    " + "If \"\\c\" appears anywhere in the pattern the whole pattern is handled as though 'ignorecase' is on. " + @@ -996,7 +1000,7 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["?"], function () { vimperator.search.openSearchDialog(vimperator.modes.SEARCH_BACKWARD); }, { - short_help: "Search backwards for a pattern", + shortHelp: "Search backwards for a pattern", usage: ["?{pattern}[?]"], help: "Search backward for the first occurrence of {pattern}.
    " + "If \"\\c\" appears anywhere in the pattern the whole pattern is handled as though 'ignorecase' is on. " + @@ -1009,14 +1013,14 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["n"], function () { vimperator.search.findAgain(false); }, { - short_help: "Find next", + shortHelp: "Find next", help: "Repeat the last search 1 time (until count is supported)." } )); addDefaultMap(new vimperator.Map(vimperator.modes.NORMAL, ["N"], function () { vimperator.search.findAgain(true); }, { - short_help: "Find previous", + shortHelp: "Find previous", help: "Repeat the last search 1 time (until count is supported) in the opposite direction." } )); @@ -1030,64 +1034,64 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, ["o"], function () { vimperator.hints.openHints(false, false); }, { - cancel_mode: true, - always_active: false + cancelMode: true, + alwaysActive: false } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, ["t"], function () { vimperator.hints.openHints(true, false); }, { - cancel_mode: true, - always_active: false + cancelMode: true, + alwaysActive: false } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], - function () { vimperator.hints.openHints(false, true ); }, + function () { vimperator.hints.openHints(false, true); }, { - cancel_mode: true, - always_active: false + cancelMode: true, + alwaysActive: false } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, ["s"], function () { vimperator.hints.saveHints(true); }, { - cancel_mode: true, - always_active: false + cancelMode: true, + alwaysActive: false } )); addDefaultMap(new vimperator.Map([vimperator.modes.HINTS], ["a"], function () { vimperator.hints.saveHints(false); }, { - cancel_mode: true, - always_active: false + cancelMode: true, + alwaysActive: false } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, ["y"], function () { vimperator.hints.yankUrlHints(); }, { - cancel_mode: true, - always_active: false + cancelMode: true, + alwaysActive: false } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, ["Y"], function () { vimperator.hints.yankTextHints(); }, { - cancel_mode: true, - always_active: false + cancelMode: true, + alwaysActive: false } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [","], function () { vimperator.input.buffer += ","; vimperator.hints.setCurrentState(0); }, { - cancel_mode: false, - always_active: true + cancelMode: false, + alwaysActive: true } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [":"], function () { vimperator.commandline.open(":", "", vimperator.modes.EX); }, { - cancel_mode: false, - always_active: true + cancelMode: false, + alwaysActive: true } )); @@ -1095,78 +1099,78 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function (count) { vimperator.buffer.scrollLines(count > 1 ? count : 1); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function (count) { vimperator.buffer.scrollLines(-(count > 1 ? count : 1)); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.buffer.scrollTop(); }, { - cancel_mode: false, - always_active: true + cancelMode: false, + alwaysActive: true } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.buffer.scrollBottom(); }, { - cancel_mode: false, - always_active: true + cancelMode: false, + alwaysActive: true } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, ["", ""], function (count) { vimperator.buffer.scrollPages(-(count > 1 ? count : 1)); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, ["", ""], function (count) { vimperator.buffer.scrollPages(count > 1 ? count : 1); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.buffer.scrollColumns(-(count > 1 ? count : 1)); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.buffer.scrollLines(count > 1 ? count : 1); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.buffer.scrollLines(-(count > 1 ? count : 1)); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.buffer.scrollColumns(count > 1 ? count : 1); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); @@ -1175,15 +1179,15 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.tabs.select("+1", true); }, { - cancel_mode: true, - always_active: true + cancelMode: true, + alwaysActive: true } )); // same as gt, but no count supported addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.tabs.select("-1", true); }, { - cancel_mode: true, - always_active: true + cancelMode: true, + alwaysActive: true } )); @@ -1191,74 +1195,76 @@ vimperator.Mappings = function () //{{{ addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function (count) { vimperator.history.stepTo(count > 0 ? -count : -1); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function (count) { vimperator.history.stepTo(count > 1 ? count : 1); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function (count) { vimperator.history.stepTo(count > 0 ? -count : -1); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function (count) { vimperator.history.stepTo(count > 1 ? count : 1); }, { - cancel_mode: false, - always_active: true, + cancelMode: false, + alwaysActive: true, flags: vimperator.Mappings.flags.COUNT } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { vimperator.tabs.remove(getBrowser().mCurrentTab, vimperator.input.count, false, 0); }, { - cancel_mode: true, - always_active: true + cancelMode: true, + alwaysActive: true } )); - // cancel_mode hint mode keys + // cancelMode hint mode keys addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { ; }, { - cancel_mode: true, - always_active: true + cancelMode: true, + alwaysActive: true } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { ; }, { - cancel_mode: true, - always_active: true + cancelMode: true, + alwaysActive: true } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { ; }, { - cancel_mode: true, - always_active: true + cancelMode: true, + alwaysActive: true } )); addDefaultMap(new vimperator.Map(vimperator.modes.HINTS, [""], function () { ; }, { - cancel_mode: true, - always_active: true + cancelMode: true, + alwaysActive: true } )); //}}} //}}} -} //}}} + + return mappingManager; +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/options.js b/content/options.js index 5ee4ab1b..149e122e 100644 --- a/content/options.js +++ b/content/options.js @@ -26,7 +26,7 @@ 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, extra_info) //{{{ +vimperator.Option = function (names, type, extraInfo) //{{{ { if (!names || !type) return null; @@ -38,29 +38,29 @@ vimperator.Option = function (names, type, extra_info) //{{{ this.usage = this.names; this.type = type; - if (extra_info) + if (extraInfo) { - if (extra_info.usage) - this.usage = extra_info.usage; + if (extraInfo.usage) + this.usage = extraInfo.usage; - this.help = extra_info.help || null; - this.short_help = extra_info.short_help || null; + this.help = extraInfo.help || null; + this.shortHelp = extraInfo.shortHelp || null; // "", 0 are valid default values - if (extra_info.default_value !== undefined) - this.default_value = extra_info.default_value; + if (extraInfo.defaultValue !== undefined) + this.defaultValue = extraInfo.defaultValue; else - this.default_value = null; + this.defaultValue = null; - value = this.default_value; + value = this.defaultValue; - if (extra_info.setter) - this.setter = extra_info.setter; - if (extra_info.getter) - this.getter = extra_info.getter; + if (extraInfo.setter) + this.setter = extraInfo.setter; + if (extraInfo.getter) + this.getter = extraInfo.getter; - this.completer = extra_info.completer || null; - this.validator = extra_info.validator || null; + this.completer = extraInfo.completer || null; + this.validator = extraInfo.validator || null; } // add noOPTION variant of boolean OPTION to this.names @@ -85,9 +85,9 @@ vimperator.Option = function (names, type, extra_info) //{{{ } ); this.__defineSetter__("value", - function (new_value) + function (newValue) { - value = new_value; + value = newValue; if (this.setter) this.setter.call(this, value); } @@ -104,7 +104,7 @@ vimperator.Option = function (names, type, extra_info) //{{{ return true; } return false; - } + }; this.isValidValue = function (value) { @@ -112,26 +112,27 @@ vimperator.Option = function (names, type, extra_info) //{{{ return this.validator(value); else return true; - } + }; this.reset = function () { - this.value = this.default_value; - } -} //}}} + this.value = this.defaultValue; + }; +}; //}}} vimperator.Options = function () //{{{ { //////////////////////////////////////////////////////////////////////////////// ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - var firefox_prefs = Components.classes["@mozilla.org/preferences-service;1"] + + var firefoxPrefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); - var vimperator_prefs = firefox_prefs.getBranch("extensions.vimperator."); + var vimperatorPrefs = firefoxPrefs.getBranch("extensions.vimperator."); var options = []; // save if we already changed a GUI related option, used for setInitialGUI - var guioptions_done = false, showtabline_done = false, laststatus_done = false; + var guioptionsDone = false, showtablineDone = false, laststatusDone = false; function optionsIterator() { @@ -141,14 +142,14 @@ vimperator.Options = function () //{{{ throw StopIteration; } - function storePreference(name, value, vimperator_branch) + function storePreference(name, value, vimperatorBranch) { var branch; - if (vimperator_branch) - branch = vimperator_prefs; + if (vimperatorBranch) + branch = vimperatorPrefs; else - branch = firefox_prefs; + branch = firefoxPrefs; switch (typeof value) { @@ -166,23 +167,23 @@ vimperator.Options = function () //{{{ } } - function loadPreference(name, forced_default, vimperator_branch) + function loadPreference(name, forcedDefault, vimperatorBranch) { - var default_value = null; - if (forced_default != null) // this argument sets defaults for non-user settable options (like comp_history) - default_value = forced_default; + var defaultValue = null; + if (forcedDefault != null) // this argument sets defaults for non-user settable options (like comp_history) + defaultValue = forcedDefault; - if (vimperator_branch) + if (vimperatorBranch) { - branch = vimperator_prefs; + branch = vimperatorPrefs; - if (!forced_default) // this argument sets defaults for non-user settable options (like comp_history) + if (!forcedDefault) // this argument sets defaults for non-user settable options (like comp_history) { for (var i = 0; i < options.length; i++) { if (options[i].name == name) // only first name is searched { - default_value = options[i].default_value; + defaultValue = options[i].defaultValue; break; } } @@ -190,12 +191,12 @@ vimperator.Options = function () //{{{ } else { - branch = firefox_prefs; + branch = firefoxPrefs; } try { - switch (typeof default_value) + switch (typeof defaultValue) { case "string": return branch.getCharPref(name); @@ -204,12 +205,12 @@ vimperator.Options = function () //{{{ case "boolean": return branch.getBoolPref(name); default: - return default_value; + return defaultValue; } } catch (e) { - return default_value; + return defaultValue; } } @@ -225,7 +226,7 @@ vimperator.Options = function () //{{{ document.getElementById("PersonalToolbar").collapsed = value.indexOf("b") > -1 ? false : true; document.getElementById("PersonalToolbar").hidden = value.indexOf("b") > -1 ? false : true; - guioptions_done = true; + guioptionsDone = true; } function setLastStatus(value) @@ -245,7 +246,7 @@ vimperator.Options = function () //{{{ document.getElementById("status-bar").hidden = false; } - laststatus_done = true; + laststatusDone = true; } function setShowTabline(value) @@ -269,7 +270,7 @@ vimperator.Options = function () //{{{ tabs.collapsed = false; } - showtabline_done = true; + showtablineDone = true; } function setTitleString(value) @@ -296,9 +297,9 @@ vimperator.Options = function () //{{{ // // work around firefox popup blocker - var popup_allowed_events = loadPreference("dom.popup_allowed_events", "change click dblclick mouseup reset submit"); - if (!popup_allowed_events.match("keypress")) - storePreference("dom.popup_allowed_events", popup_allowed_events + " keypress"); + var popupAllowedEvents = loadPreference("dom.popup_allowed_events", "change click dblclick mouseup reset submit"); + if (!popupAllowedEvents.match("keypress")) + storePreference("dom.popup_allowed_events", popupAllowedEvents + " keypress"); // TODO: shouldn't we be resetting these in destroy() as well? // we have our own typeahead find implementation @@ -312,110 +313,114 @@ vimperator.Options = function () //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - this.__iterator__ = function () - { - return optionsIterator(); - } + var optionManager = { - this.get = function (name) - { - for (var i = 0; i < options.length; i++) + __iterator__: function () { - if (options[i].hasName(name)) - return options[i]; - } - return null; - } + return optionsIterator(); + }, - this.add = function (option) - { - this.__defineGetter__(option.name, function () { return option.value; }); - this.__defineSetter__(option.name, function (value) { option.value = value; }); - options.push(option); - } - - this.destroy = function () - { - // reset some modified firefox prefs - if (loadPreference("dom.popup_allowed_events", "change click dblclick mouseup reset submit") - == popup_allowed_events + " keypress") - storePreference("dom.popup_allowed_events", popup_allowed_events); - } - - this.list = function (only_non_default) - { - // TODO: columns like Vim? - var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
    " + - ""; - var name, value, def; - - for (var i = 0; i < options.length; i++) + get: function (name) { - name = options[i].name; - value = options[i].value; - def = options[i].default_value; - - if (only_non_default && value == def) - continue; - - if (options[i].type == "boolean") + for (var i = 0; i < options.length; i++) { - name = value ? " " + name : "no" + name; - if (value != def) - name = "" + name + " (default: " + (def ? "" : "no") + options[i].name + ")"; - list += ""; + if (options[i].hasName(name)) + return options[i]; } - else + 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) + { + // TODO: columns like Vim? + var list = ":" + vimperator.util.escapeHTML(vimperator.commandline.getCommand()) + "
    " + + "
    --- Options ---
    " + name + "
    "; + var name, value, def; + + for (var i = 0; i < options.length; i++) { - if (value != def) + name = options[i].name; + value = options[i].value; + def = options[i].defaultValue; + + if (onlyNondefault && value == def) + continue; + + if (options[i].type == "boolean") { - name = "" + name + ""; - value = vimperator.util.colorize(value, false) + " (default: " + def + ")"; + name = value ? " " + name : "no" + name; + if (value != def) + name = "" + name + " (default: " + (def ? "" : "no") + options[i].name + ")"; + list += ""; } else - value = vimperator.util.colorize(value, false); + { + if (value != def) + { + name = "" + name + ""; + value = vimperator.util.colorize(value, false) + " (default: " + def + ")"; + } + else + value = vimperator.util.colorize(value, false); - list += ""; + list += ""; + } } + + list += "
    --- Options ---
    " + name + "
    " + " " + name + "=" + value + "
    " + " " + name + "=" + value + "
    "; + + 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 (!guioptionsDone) + this.get("guioptions").reset(); + if (!laststatusDone) + this.get("laststatus").reset(); + if (!showtablineDone) + this.get("showtabline").reset(); + }, + + // TODO: separate Preferences from Options? Would these utility functions + // be better placed in the 'core' vimperator namespace somewhere? + setPref: function (name, value) + { + return storePreference(name, value, true); + }, + + getPref: function (name, forcedDefault) + { + return loadPreference(name, forcedDefault, true); + }, + + setFirefoxPref: function (name, value) + { + return storePreference(name, value); + }, + + getFirefoxPref: function (name, forcedDefault) + { + return loadPreference(name, forcedDefault); } - list += ""; - - 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 - this.setInitialGUI = function () - { - if (!guioptions_done) - this.get("guioptions").reset(); - if (!laststatus_done) - this.get("laststatus").reset(); - if (!showtabline_done) - this.get("showtabline").reset(); - } - - // TODO: separate Preferences from Options? Would these utility functions - // be better placed in the 'core' vimperator namespace somewhere? - this.setPref = function (name, value) - { - return storePreference(name, value, true); - } - - this.getPref = function (name, forced_default) - { - return loadPreference(name, forced_default, true); - } - - this.setFirefoxPref = function (name, value) - { - return storePreference(name, value); - } - - this.getFirefoxPref = function (name, forced_default) - { - return loadPreference(name, forced_default); - } + }; /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// DEFAULT OPTIONS ///////////////////////////////////////// @@ -424,11 +429,11 @@ vimperator.Options = function () //{{{ 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" + "//xhtml:input[not(@type='hidden')] | //xhtml:a | //xhtml:area | //xhtml:iframe | //xhtml:textarea | //xhtml:button | //xhtml:select"; - this.add(new vimperator.Option(["activate", "act"], "stringlist", + optionManager.add(new vimperator.Option(["activate", "act"], "stringlist", { - short_help: "Define when tabs are automatically activated", + shortHelp: "Define when tabs are automatically activated", help: "Available items:
    " + "
      " + "
    • homepage: gH mapping
    • " + @@ -436,16 +441,16 @@ vimperator.Options = function () //{{{ "
    • tabopen: :tabopen[!] command
    • " + "
    • paste: P and gP mappings
    • " + "
    ", - default_value: "homepage,quickmark,tabopen,paste", + defaultValue: "homepage,quickmark,tabopen,paste", validator: function (value) { return value.split(",").every(function (item) { return /^(homepage|quickmark|tabopen|paste|)$/.test(item); }); } } )); - this.add(new vimperator.Option(["complete", "cpt"], "charlist", + optionManager.add(new vimperator.Option(["complete", "cpt"], "charlist", { - short_help: "Items which are completed at the :[tab]open prompt", + shortHelp: "Items which are completed at the :[tab]open prompt", help: "Available items:
    " + "
      " + "
    • s: Search engines and keyword URLs
    • " + @@ -455,43 +460,42 @@ vimperator.Options = function () //{{{ "
    " + "The order is important, so :set complete=bs would list bookmarks first, and then any available quick searches.
    " + "Add 'sort' to the 'wildoptions' option if you want all entries sorted.", - default_value: "sfbh", + defaultValue: "sfbh", validator: function (value) { return !/[^sfbh]/.test(value); } } )); - this.add(new vimperator.Option(["defsearch", "ds"], "string", + optionManager.add(new vimperator.Option(["defsearch", "ds"], "string", { - short_help: "Set the default search engine", + shortHelp: "Set the default search engine", help: "The default search engine is used in the :[tab]open [arg] command " + "if [arg] neither looks like a URL or like a specified search engine/keyword.", - completer: function () { return [["foo", "bar"], ["shit", "blub"]]; }, - default_value: "google" + defaultValue: "google" } )); - this.add(new vimperator.Option(["extendedhinttags", "eht"], "string", + optionManager.add(new vimperator.Option(["extendedhinttags", "eht"], "string", { - short_help: "XPath string of hintable elements activated by ';'", - default_value: DEFAULT_HINTTAGS + shortHelp: "XPath string of hintable elements activated by ';'", + defaultValue: DEFAULT_HINTTAGS } )); - this.add(new vimperator.Option(["focusedhintstyle", "fhs"], "string", + optionManager.add(new vimperator.Option(["focusedhintstyle", "fhs"], "string", { - short_help: "CSS specification of focused hints", - default_value: "z-index:5000; font-family:monospace; font-size:12px; color:ButtonText; background-color:ButtonShadow; " + + 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;" } )); - this.add(new vimperator.Option(["fullscreen", "fs"], "boolean", + optionManager.add(new vimperator.Option(["fullscreen", "fs"], "boolean", { - short_help: "Show the current window fullscreen", + shortHelp: "Show the current window fullscreen", setter: function (value) { window.fullScreen = value; }, getter: function () { return window.fullScreen; }, - default_value: false + defaultValue: false } )); - this.add(new vimperator.Option(["guioptions", "go"], "charlist", + optionManager.add(new vimperator.Option(["guioptions", "go"], "charlist", { - short_help: "Show or hide the menu, toolbar and scrollbars", + shortHelp: "Show or hide the menu, toolbar and scrollbars", help: "Supported characters:
    " + "
      " + "
    • m: menubar
    • " + @@ -499,58 +503,58 @@ vimperator.Options = function () //{{{ "
    • b: bookmark bar
    • " + "
    ", setter: function (value) { setGuiOptions(value); }, - default_value: "", + defaultValue: "", validator: function (value) { return !/[^mTb]/.test(value); } } )); - this.add(new vimperator.Option(["hintchars", "hc"], "charlist", + optionManager.add(new vimperator.Option(["hintchars", "hc"], "charlist", { - short_help: "String of single characters which can be used to follow hints", - default_value: "hjklasdfgyuiopqwertnmzxcvb" + shortHelp: "String of single characters which can be used to follow hints", + defaultValue: "hjklasdfgyuiopqwertnmzxcvb" } )); - this.add(new vimperator.Option(["hintstyle", "hs"], "string", + optionManager.add(new vimperator.Option(["hintstyle", "hs"], "string", { - short_help: "CSS specification of unfocused hints", - default_value: "z-index:5000; font-family:monospace; font-size:12px; color:white; background-color:red; " + + 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;" } )); - this.add(new vimperator.Option(["hinttags", "ht"], "string", + optionManager.add(new vimperator.Option(["hinttags", "ht"], "string", { - short_help: "XPath string of hintable elements activated by 'f' and 'F'", - default_value: DEFAULT_HINTTAGS + shortHelp: "XPath string of hintable elements activated by 'f' and 'F'", + defaultValue: DEFAULT_HINTTAGS } )); - this.add(new vimperator.Option(["hlsearch", "hls"], "boolean", + optionManager.add(new vimperator.Option(["hlsearch", "hls"], "boolean", { - short_help: "Highlight previous search pattern matches", + shortHelp: "Highlight previous search pattern matches", setter: function (value) { if (value) vimperator.search.highlight(); else vimperator.search.clear(); }, - default_value: false + defaultValue: false } )); - this.add(new vimperator.Option(["hlsearchstyle", "hlss"], "string", + optionManager.add(new vimperator.Option(["hlsearchstyle", "hlss"], "string", { - short_help: "CSS specification of highlighted search items", - default_value: "color: black; background-color: yellow; padding: 0; display: inline;" + shortHelp: "CSS specification of highlighted search items", + defaultValue: "color: black; background-color: yellow; padding: 0; display: inline;" } )); - this.add(new vimperator.Option(["ignorecase", "ic"], "boolean", + optionManager.add(new vimperator.Option(["ignorecase", "ic"], "boolean", { - short_help: "Ignore case in search patterns", - default_value: true + shortHelp: "Ignore case in search patterns", + defaultValue: true } )); - this.add(new vimperator.Option(["incsearch", "is"], "boolean", + optionManager.add(new vimperator.Option(["incsearch", "is"], "boolean", { - short_help: "Show where the search pattern matches as it is typed", + shortHelp: "Show where the search pattern matches as it is typed", help: "NOTE: Incremental searching currently only works in the forward direction.", - default_value: true + defaultValue: true } )); - this.add(new vimperator.Option(["laststatus", "ls"], "number", + optionManager.add(new vimperator.Option(["laststatus", "ls"], "number", { - short_help: "Show the status line", + shortHelp: "Show the status line", help: "Determines when the last window will have a status line. " + "Possible values:
    " + "
      " + @@ -559,35 +563,35 @@ vimperator.Options = function () //{{{ "
    • 2: always
    • " + "
    " + "NOTE: laststatus=1 not implemented yet.", - default_value: 2, + defaultValue: 2, setter: function (value) { setLastStatus(value); }, validator: function (value) { return (value >= 0 && value <= 2); } } )); - this.add(new vimperator.Option(["linksearch", "lks"], "boolean", + optionManager.add(new vimperator.Option(["linksearch", "lks"], "boolean", { - short_help: "Limit the search to hyperlink text", + shortHelp: "Limit the search to hyperlink text", help: "This includes (X)HTML elements with an \"href\" atrribute and XLink \"simple\" links.", - default_value: false + defaultValue: false } )); - this.add(new vimperator.Option(["more"], "boolean", + optionManager.add(new vimperator.Option(["more"], "boolean", { - short_help: "Pause the message list window when more than one screen of listings is displayed", - default_value: true + shortHelp: "Pause the message list window when more than one screen of listings is displayed", + defaultValue: true } )); - this.add(new vimperator.Option(["maxhints", "mh"], "number", + optionManager.add(new vimperator.Option(["maxhints", "mh"], "number", { - short_help: "Maximum number of simultaneously shown hints", + shortHelp: "Maximum number of simultaneously shown hints", help: "If you want to speed up display of hints, choose a smaller value", - default_value: 250, + defaultValue: 250, validator: function (value) { if (value >= 1 && value <= 1000) return true; else return false; } } )); - this.add(new vimperator.Option(["pageinfo", "pa"], "charlist", + optionManager.add(new vimperator.Option(["pageinfo", "pa"], "charlist", { - short_help: "Desired info on :pa[geinfo]", + shortHelp: "Desired info on :pa[geinfo]", help: "Available items:
    " + "
      " + "
    • g: general info
    • " + @@ -595,13 +599,13 @@ vimperator.Options = function () //{{{ "
    • m: meta tags
    • " + "
    " + "The order matters", - default_value: "gfm", - validator: function (value) { return !(/[^gfm]/.test(value) || value.length > 3 || value.length < 1) } + defaultValue: "gfm", + validator: function (value) { return !(/[^gfm]/.test(value) || value.length > 3 || value.length < 1); } } )); - this.add(new vimperator.Option(["popups", "pps"], "number", + optionManager.add(new vimperator.Option(["popups", "pps"], "number", { - short_help: "Where to show requested popup windows", + shortHelp: "Where to show requested popup windows", help: "Define where to show requested popup windows. Does not apply to windows which are opened by middle clicking a link, they always open in a new tab. " + "Possible values:
    " + "
      " + @@ -611,48 +615,48 @@ vimperator.Options = function () //{{{ "
    • 3: Always open in a new window
    • " + "
    " + "NOTE: This option does not change the popup blocker of Firefox in any way.", - default_value: 1, + defaultValue: 1, setter: function (value) { setPopups(value); }, validator: function (value) { return (value >= 0 && value <= 3); } } )); - this.add(new vimperator.Option(["preload"], "boolean", + optionManager.add(new vimperator.Option(["preload"], "boolean", { - short_help: "Speed up first time history/bookmark completion", + shortHelp: "Speed up first time history/bookmark completion", help: "History access can be quite slow for a large history. Vimperator maintains a cache to speed it up significantly on subsequent access.
    " + "In order to also speed up first time access, it is cached at startup, if this option is set (recommended).", - default_value: true + defaultValue: true } )); - this.add(new vimperator.Option(["previewheight", "pvh"], "number", + optionManager.add(new vimperator.Option(["previewheight", "pvh"], "number", { - short_help: "Default height for preview window", + shortHelp: "Default height for preview window", help: "Value must be between 1 and 50. If the value is too high, completions may cover the command-line. " + "Close the preview window with :pclose.
    " + "NOTE: Option currently disabled", - default_value: 10, + defaultValue: 10, validator: function (value) { return (value >= 1 && value <= 50); } } )); - this.add(new vimperator.Option(["scroll", "scr"], "number", + optionManager.add(new vimperator.Option(["scroll", "scr"], "number", { - short_help: "Number of lines to scroll with C-u and C-d commands", + shortHelp: "Number of lines to scroll with C-u and C-d commands", help: "The number of lines scrolled defaults to half the window size. " + "When a {count} is specified to the <C-u> or <C-d> commands this is used to set the value of 'scroll' and also used for the current command. " + "The value can be reset to half the window height with :set scroll=0.", - default_value: 0, + defaultValue: 0, validator: function (value) { return value >= 0; } } )); - this.add(new vimperator.Option(["showmode", "smd"], "boolean", + optionManager.add(new vimperator.Option(["showmode", "smd"], "boolean", { - short_help: "Show the current mode in the command line", - default_value: true + shortHelp: "Show the current mode in the command line", + defaultValue: true } )); - this.add(new vimperator.Option(["showstatuslinks", "ssli"], "number", + optionManager.add(new vimperator.Option(["showstatuslinks", "ssli"], "number", { - short_help: "Show the destination of the link under the cursor in the status bar", + shortHelp: "Show the destination of the link under the cursor in the status bar", help: "Also links which are focused by keyboard commands like <Tab> are shown. " + "Possible values:
    " + "
      " + @@ -660,13 +664,13 @@ vimperator.Options = function () //{{{ "
    • 1: Show the link in the status line
    • " + "
    • 2: Show the link in the command line
    • " + "
    ", - default_value: 1, + defaultValue: 1, validator: function (value) { return (value >= 0 && value <= 2); } } )); - this.add(new vimperator.Option(["showtabline", "stal"], "number", + optionManager.add(new vimperator.Option(["showtabline", "stal"], "number", { - short_help: "Control when to show the tab bar of opened web pages", + shortHelp: "Control when to show the tab bar of opened web pages", help: "Possible values:
    " + "
      " + "
    • 0: Never show tab bar
    • " + @@ -674,63 +678,63 @@ vimperator.Options = function () //{{{ "
    • 2: Always show tab bar
    • " + "
    ", setter: function (value) { setShowTabline(value); }, - default_value: 2, + defaultValue: 2, validator: function (value) { return (value >= 0 && value <= 2); } } )); - this.add(new vimperator.Option(["smartcase", "scs"], "boolean", + optionManager.add(new vimperator.Option(["smartcase", "scs"], "boolean", { - short_help: "Override the 'ignorecase' option if the pattern contains uppercase characters", + shortHelp: "Override the 'ignorecase' option if the pattern contains uppercase characters", help: "This is only used if the 'ignorecase' option is set.", - default_value: true + defaultValue: true } )); - this.add(new vimperator.Option(["titlestring"], "string", + optionManager.add(new vimperator.Option(["titlestring"], "string", { - short_help: "Change the title of the browser window", + shortHelp: "Change the title of the browser window", help: "Vimperator changes the browser title from \"Title of web page - Mozilla Firefox\" to " + "\"Title of web page - Vimperator\".
    If you don't like that, you can restore it with: " + ":set titlestring=Mozilla Firefox.", setter: function (value) { setTitleString(value); }, - default_value: "Vimperator" + defaultValue: "Vimperator" } )); - this.add(new vimperator.Option(["usermode", "um"], "boolean", + optionManager.add(new vimperator.Option(["usermode", "um"], "boolean", { - short_help: "Show current website with a minimal style sheet to make it easily accessible", + shortHelp: "Show current website with a minimal style sheet to make it easily accessible", help: "Note that this is a local option for now, later it may be split into a global and :setlocal part", setter: function (value) { getMarkupDocumentViewer().authorStyleDisabled = value; }, getter: function () { return getMarkupDocumentViewer().authorStyleDisabled; }, - default_value: false + defaultValue: false } )); - this.add(new vimperator.Option(["verbose", "vbs"], "number", + optionManager.add(new vimperator.Option(["verbose", "vbs"], "number", { - short_help: "Define which type of messages are logged", + shortHelp: "Define which type of messages are logged", help: "When bigger than zero, Vimperator will give messages about what it is doing. They are printed to the error console which can be shown with :javascript!.
    " + "The highest value is 9, being the most verbose mode.", - default_value: 0, + defaultValue: 0, validator: function (value) { return (value >= 0 && value <= 9); } } )); - this.add(new vimperator.Option(["visualbell", "vb"], "boolean", + optionManager.add(new vimperator.Option(["visualbell", "vb"], "boolean", { - short_help: "Use visual bell instead of beeping on errors", + shortHelp: "Use visual bell instead of beeping on errors", setter: function (value) { vimperator.options.setFirefoxPref("accessibility.typeaheadfind.enablesound", !value); }, - default_value: false + defaultValue: false } )); - this.add(new vimperator.Option(["visualbellstyle", "t_vb"], "string", + optionManager.add(new vimperator.Option(["visualbellstyle", "t_vb"], "string", { - short_help: "CSS specification of the visual bell", + shortHelp: "CSS specification of the visual bell", help: "To hide the visual bell use a value of \"display: none;\" or unset it with :set t_vb=", setter: function (value) { if (!value) value = "display: none;"; }, - default_value: "background-color: black; color: black;" + defaultValue: "background-color: black; color: black;" } )); - this.add(new vimperator.Option(["wildmode", "wim"], "stringlist", + optionManager.add(new vimperator.Option(["wildmode", "wim"], "stringlist", { - short_help: "Define how command line completion works", + shortHelp: "Define how command line completion works", help: "It is a comma-separated list of parts, where each part specifies " + "what to do for each consecutive use of the completion key. The first part " + "specifies the behavior for the first use of the completion key, the second part " + @@ -745,22 +749,22 @@ vimperator.Options = function () //{{{ "'list:longest'When more than one match, list all matches and complete till the longest common string." + "" + "When there is only a single match, it is fully completed regardless of the case.", - default_value: "list:full", + defaultValue: "list:full", validator: function (value) { return value.split(",").every(function (item) { return /^(full|longest|list|list:full|list:longest|)$/.test(item); }); } } )); - this.add(new vimperator.Option(["wildoptions", "wop"], "stringlist", + optionManager.add(new vimperator.Option(["wildoptions", "wop"], "stringlist", { - short_help: "Change how command line completion is done", + shortHelp: "Change how command line completion is done", help: "A list of words that change how command line completion is done.
    " + "Currently only one word is allowed:
    " + "" + "" + "
    sortAlways sorts completion list, overriding the 'complete' option.
    ", - default_value: "", + defaultValue: "", validator: function (value) { return /^(sort|)$/.test(value); } } )); @@ -771,10 +775,12 @@ vimperator.Options = function () //{{{ setShowTabline(0); setGuiOptions(""); setLastStatus(0); - guioptions_done = showtabline_done = laststatus_done = false; + guioptionsDone = showtablineDone = laststatusDone = false; - setTitleString(this.titlestring); - setPopups(this.popups); -} //}}} + 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 3e761fae..cb5ef4e5 100644 --- a/content/tabs.js +++ b/content/tabs.js @@ -38,13 +38,12 @@ vimperator.Tabs = function () //{{{ ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - /** @param spec can either be: - * - an absolute integer - * - "" for the current tab - * - "+1" for the next tab - * - "-3" for the tab, which is 3 positions left of the current - * - "$" for the last tab - */ + // @param spec can either be: + // - an absolute integer + // - "" for the current tab + // - "+1" for the next tab + // - "-3" for the tab, which is 3 positions left of the current + // - "$" for the last tab function indexFromSpec(spec, wrap) { var position = getBrowser().tabContainer.selectedIndex; @@ -58,7 +57,7 @@ vimperator.Tabs = function () //{{{ position = spec; else if (spec === "$") return last; - else if (!spec.match(/^([+-]?\d+|)$/)) + else if (!/^([+-]?\d+|)$/.test(spec)) { // TODO: move error reporting to ex-command? vimperator.echoerr("E488: Trailing characters"); @@ -66,7 +65,7 @@ vimperator.Tabs = function () //{{{ } else { - if (spec.match(/^([+-]\d+)$/)) // relative position +/-N + if (/^([+-]\d+)$/.test(spec)) // relative position +/-N position += parseInt(spec, 10); else // absolute position position = parseInt(spec, 10); @@ -80,195 +79,192 @@ vimperator.Tabs = function () //{{{ return position; } - var alternates = [null, null]; + var alternates = [getBrowser().mCurrentTab, null]; /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - // @returns the index of the currently selected tab starting with 0 - this.index = function (tab) - { - if (tab) + return { + + get alternate() { return alternates[1]; }, + + get count() { return getBrowser().mTabs.length; }, + + // @returns the index of the currently selected tab starting with 0 + index: function (tab) { - var length = getBrowser().mTabs.length; - for (var i = 0; i < length; i++) + if (tab) { - if (getBrowser().mTabs[i] == tab) - return i; - } - return -1; - } - - return getBrowser().tabContainer.selectedIndex; - } - - this.count = function () - { - return getBrowser().mTabs.length; - } - - // TODO: implement filter - // @returns an array of tabs which match filter - this.get = function (filter) - { - var buffers = []; - var browsers = getBrowser().browsers; - for (var i in browsers) - { - var title = browsers[i].contentTitle || "(Untitled)"; - var uri = browsers[i].currentURI.spec; - var number = i + 1; - buffers.push([number, title, uri]); - } - return buffers; - } - - this.getTab = function (index) - { - if (index) - return getBrowser().mTabs[index]; - - return getBrowser().tabContainer.selectedItem; - } - - /* spec == "" moves the tab to the last position as per Vim - * wrap causes the movement to wrap around the start and end of the tab list - * NOTE: position is a 0 based index - * FIXME: tabmove! N should probably produce an error - */ - this.move = function (tab, spec, wrap) - { - if (spec === "") - spec = "$"; // if not specified, move to the last tab -> XXX: move to ex handling? - - var index = indexFromSpec(spec, wrap); - getBrowser().moveTabTo(tab, index); - } - - /* quit_on_last_tab = 1: quit without saving session - * quit_on_last_tab = 2: quit and save session - */ - this.remove = function (tab, count, focus_left_tab, quit_on_last_tab) - { - function removeOrBlankTab (tab) - { - if (getBrowser().mTabs.length > 1) - getBrowser().removeTab(tab); - else - { - if (vimperator.buffer.URL != "about:blank" || - getWebNavigation().sessionHistory.count > 0) + var length = getBrowser().mTabs.length; + for (var i = 0; i < length; i++) { - vimperator.open("about:blank", vimperator.NEW_BACKGROUND_TAB); + if (getBrowser().mTabs[i] == tab) + return i; + } + return -1; + } + + return getBrowser().tabContainer.selectedIndex; + }, + + // TODO: implement filter + // @returns an array of tabs which match filter + get: function (filter) + { + var buffers = []; + var browsers = getBrowser().browsers; + for (var i in browsers) + { + var title = browsers[i].contentTitle || "(Untitled)"; + var uri = browsers[i].currentURI.spec; + var number = i + 1; + buffers.push([number, title, uri]); + } + return buffers; + }, + + getTab: function (index) + { + if (index) + return getBrowser().mTabs[index]; + + return getBrowser().tabContainer.selectedItem; + }, + + // spec == "" moves the tab to the last position as per Vim + // wrap causes the movement to wrap around the start and end of the tab list + // NOTE: position is a 0 based index + // FIXME: tabmove! N should probably produce an error + move: function (tab, spec, wrap) + { + if (spec === "") + spec = "$"; // if not specified, move to the last tab -> XXX: move to ex handling? + + var index = indexFromSpec(spec, wrap); + getBrowser().moveTabTo(tab, index); + }, + + // quitOnLastTab = 1: quit without saving session + // quitOnLastTab = 2: quit and save session + remove: function (tab, count, focusLeftTab, quitOnLastTab) + { + function removeOrBlankTab (tab) + { + if (getBrowser().mTabs.length > 1) getBrowser().removeTab(tab); - } else - vimperator.beep(); + { + if (vimperator.buffer.URL != "about:blank" || + getWebNavigation().sessionHistory.count > 0) + { + vimperator.open("about:blank", vimperator.NEW_BACKGROUND_TAB); + getBrowser().removeTab(tab); + } + else + vimperator.beep(); + } } - } - if (count < 1) - count = 1; + if (count < 1) + count = 1; - if (quit_on_last_tab >= 1 && getBrowser().mTabs.length <= count) - { - if (vimperator.windows.length > 1) - window.close(); + if (quitOnLastTab >= 1 && getBrowser().mTabs.length <= count) + { + if (vimperator.windows.length > 1) + window.close(); + else + vimperator.quit(quitOnLastTab == 2); + + return; + } + + var index = this.index(tab); + if (focusLeftTab) + { + var lastRemovedTab = 0; + for (var i = index; i > index - count && i >= 0; i--) + { + removeOrBlankTab(this.getTab(i)); + lastRemovedTab = i > 0 ? i : 1; + } + getBrowser().mTabContainer.selectedIndex = lastRemovedTab - 1; + } else - vimperator.quit(quit_on_last_tab == 2); - - return; - } - - var index = this.index(tab); - if (focus_left_tab) - { - var last_removed_tab = 0; - for (var i = index; i > index - count && i >= 0; i--) { - removeOrBlankTab(this.getTab(i)); - last_removed_tab = i > 0 ? i : 1; + var i = index + count - 1; + if (i >= this.count) + i = this.count - 1; + + for (; i >= index; i--) + removeOrBlankTab(this.getTab(i)); } - getBrowser().mTabContainer.selectedIndex = last_removed_tab - 1; - } - else + }, + + keepOnly: function (tab) { - var i = index + count - 1; - if (i >= this.count()) - i = this.count() - 1; + getBrowser().removeAllTabsBut(tab); + }, - for (; i >= index; i--) - removeOrBlankTab(this.getTab(i)); - } - } - - this.keepOnly = function (tab) - { - getBrowser().removeAllTabsBut(tab); - } - - this.select = function (spec, wrap) - { - var index = indexFromSpec(spec, wrap); - if (index === false) + select: function (spec, wrap) { - vimperator.beep(); // XXX: move to ex-handling? - return false; - } - getBrowser().mTabContainer.selectedIndex = index; - } - - // TODO: when restarting a session FF selects the first tab and then the - // tab that was selected when the session was created. As a result the - // alternate after a restart is often incorrectly tab 1 when there - // shouldn't be one yet. - this.updateSelectionHistory = function () - { - alternates = [this.getTab(), alternates[0]]; - this.alternate = alternates[1]; - } - - // TODO: move to v.buffers - this.alternate = this.getTab(); - - this.reload = function (tab, bypass_cache) - { - if (bypass_cache) - { - const nsIWebNavigation = Components.interfaces.nsIWebNavigation; - const flags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE; - getBrowser().getBrowserForTab(tab).reloadWithFlags(flags); - } - else - { - getBrowser().reloadTab(tab); - } - } - - this.reloadAll = function (bypass_cache) - { - if (bypass_cache) - { - for (var i = 0; i < getBrowser().mTabs.length; i++) + var index = indexFromSpec(spec, wrap); + if (index === false) { - try + vimperator.beep(); // XXX: move to ex-handling? + return false; + } + getBrowser().mTabContainer.selectedIndex = index; + }, + + // TODO: when restarting a session FF selects the first tab and then the + // tab that was selected when the session was created. As a result the + // alternate after a restart is often incorrectly tab 1 when there + // shouldn't be one yet. + updateSelectionHistory: function () + { + alternates = [this.getTab(), alternates[0]]; + }, + + reload: function (tab, bypassCache) + { + if (bypassCache) + { + const nsIWebNavigation = Components.interfaces.nsIWebNavigation; + const flags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE; + getBrowser().getBrowserForTab(tab).reloadWithFlags(flags); + } + else + { + getBrowser().reloadTab(tab); + } + }, + + reloadAll: function (bypassCache) + { + if (bypassCache) + { + for (var i = 0; i < getBrowser().mTabs.length; i++) { - this.reload(getBrowser().mTabs[i], bypass_cache) - } - catch (e) - { - // FIXME: can we do anything useful here without stopping the - // other tabs from reloading? + try + { + this.reload(getBrowser().mTabs[i], bypassCache); + } + catch (e) + { + // FIXME: can we do anything useful here without stopping the + // other tabs from reloading? + } } } + else + { + getBrowser().reloadAllTabs(); + } } - else - { - getBrowser().reloadAllTabs(); - } - } + + }; //}}} -} //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/ui.js b/content/ui.js index 993e2c7b..c7f24753 100644 --- a/content/ui.js +++ b/content/ui.js @@ -40,7 +40,7 @@ vimperator.CommandLine = function () //{{{ const UNINITIALIZED = -2; // notifies us, if we need to start history/tab-completion from the beginning - var completionlist = new vimperator.InformationList("vimperator-completion", { min_items: 2, max_items: 10 }); + var completionlist = new vimperator.InformationList("vimperator-completion", { minItems: 2, maxItems: 10 }); var completions = []; // TODO: clean this up when it's not 3am... @@ -88,75 +88,75 @@ vimperator.CommandLine = function () //{{{ }; history.load(); - var history_index = UNINITIALIZED; - var history_start = ""; + var historyIndex = UNINITIALIZED; + var historyStart = ""; // for the example command "open sometext| othertext" (| is the cursor pos): - var completion_start_index = 0; // will be 5 because we want to complete arguments for the :open command - var completion_prefix = ""; // will be: "open sometext" - var completion_postfix = ""; // will be: " othertext" + var completionStartIndex = 0; // will be 5 because we want to complete arguments for the :open command + var completionPrefix = ""; // will be: "open sometext" + var completionPostfix = ""; // will be: " othertext" - var wild_index = 0; // keep track how often we press in a row - var completion_index = UNINITIALIZED; + var wildIndex = 0; // keep track how often we press in a row + var completionIndex = UNINITIALIZED; - // the containing box for the prompt_widget and command_widget - var commandline_widget = document.getElementById("vimperator-commandline"); + // the containing box for the promptWidget and commandWidget + var commandlineWidget = document.getElementById("vimperator-commandline"); // the prompt for the current command, for example : or /. Can be blank - var prompt_widget = document.getElementById("vimperator-commandline-prompt"); + var promptWidget = document.getElementById("vimperator-commandline-prompt"); // the command bar which contains the current command - var command_widget = document.getElementById("vimperator-commandline-command"); + var commandWidget = document.getElementById("vimperator-commandline-command"); // the widget used for multiline output - var multiline_output_widget = document.getElementById("vimperator-multiline-output"); - multiline_output_widget.contentDocument.body.setAttribute("style", "margin: 0px; font-family: -moz-fixed;"); // get rid of the default border - multiline_output_widget.contentDocument.body.innerHTML = ""; + var multilineOutputWidget = document.getElementById("vimperator-multiline-output"); + multilineOutputWidget.contentDocument.body.setAttribute("style", "margin: 0px; font-family: -moz-fixed;"); // get rid of the default border + multilineOutputWidget.contentDocument.body.innerHTML = ""; // the widget used for multiline intput - var multiline_input_widget = document.getElementById("vimperator-multiline-input"); + var multilineInputWidget = document.getElementById("vimperator-multiline-input"); // we need to save the mode which were in before opening the command line // this is then used if we focus the command line again without the "official" // way of calling "open" - var cur_extended_mode = null; // the extended mode which we last openend the command line for - var cur_prompt = null; - var cur_command = null; - var old_mode = null; // when we leave the command prompt this mode is restored - var old_extended_mode = null; + var currentExtendedMode = null; // the extended mode which we last openend the command line for + var currentPrompt = null; + var currentCommand = null; + var oldMode = null; // when we leave the command prompt this mode is restored + var oldExtendedMode = null; // save the arguments for the inputMultiline method which are needed in the event handler - var multiline_regexp = null; - var multiline_callback = null; + var multilineRegexp = null; + var multilineCallback = null; function setHighlightGroup(group) { - commandline_widget.setAttribute("class", group); + commandlineWidget.setAttribute("class", group); } // sets the prompt - for example, : or / function setPrompt(pmt) { - prompt_widget.value = pmt; + promptWidget.value = pmt; if (pmt) { - prompt_widget.size = pmt.length; - prompt_widget.collapsed = false; + promptWidget.size = pmt.length; + promptWidget.collapsed = false; } else { - prompt_widget.collapsed = true; + promptWidget.collapsed = true; } } // sets the command - e.g. 'tabopen', 'open http://example.com/' function setCommand(cmd) { - command_widget.value = cmd; + commandWidget.value = cmd; } - function setLine(str, highlight_group) + function setLine(str, highlightGroup) { - setHighlightGroup(highlight_group); + setHighlightGroup(highlightGroup); setPrompt(""); setCommand(str); } @@ -164,58 +164,58 @@ vimperator.CommandLine = function () //{{{ // TODO: extract CSS // : resize upon a window resize // : echoed lines longer than v-c-c.width should wrap and use MOW - function setMultiline(str, highlight_group) + function setMultiline(str, highlightGroup) { - multiline_input_widget.collapsed = true; + multilineInputWidget.collapsed = true; - var output = "
    " + str + "
    "; - if (!multiline_output_widget.collapsed) + var output = "
    " + str + "
    "; + if (!multilineOutputWidget.collapsed) { // FIXME: need to make sure an open MOW is closed when commands // that don't generate output are executed - output = multiline_output_widget.contentDocument.body.innerHTML + output; - multiline_output_widget.collapsed = true; + output = multilineOutputWidget.contentDocument.body.innerHTML + output; + multilineOutputWidget.collapsed = true; } - var font_size = document.defaultView.getComputedStyle(document.getElementById("main-window"), null).getPropertyValue("font-size"); - multiline_output_widget.contentDocument.body.setAttribute("style", "font-size: " + font_size); + var fontSize = document.defaultView.getComputedStyle(document.getElementById("main-window"), null).getPropertyValue("font-size"); + multilineOutputWidget.contentDocument.body.setAttribute("style", "font-size: " + fontSize); - multiline_output_widget.contentDocument.body.innerHTML = output; - multiline_output_widget.contentDocument.body.id = "vimperator-multiline-output-content"; + multilineOutputWidget.contentDocument.body.innerHTML = output; + multilineOutputWidget.contentDocument.body.id = "vimperator-multiline-output-content"; - var stylesheet = multiline_output_widget.contentDocument.createElement("link"); + var stylesheet = multilineOutputWidget.contentDocument.createElement("link"); stylesheet.setAttribute("rel", "Stylesheet"); stylesheet.setAttribute("href", "chrome://vimperator/skin/vimperator.css"); - multiline_output_widget.contentDocument.getElementsByTagName("head")[0].appendChild(stylesheet); + multilineOutputWidget.contentDocument.getElementsByTagName("head")[0].appendChild(stylesheet); - var available_height = getBrowser().mPanelContainer.boxObject.height; - var content_height = multiline_output_widget.contentDocument.height; - var height = content_height < available_height ? content_height : available_height; + var availableHeight = getBrowser().mPanelContainer.boxObject.height; + var contentHeight = multilineOutputWidget.contentDocument.height; + var height = contentHeight < availableHeight ? contentHeight : availableHeight; - multiline_output_widget.height = height + "px"; - multiline_output_widget.collapsed = false; + multilineOutputWidget.height = height + "px"; + multilineOutputWidget.collapsed = false; - if (vimperator.options["more"] && multiline_output_widget.contentWindow.scrollMaxY > 0) + if (vimperator.options["more"] && multilineOutputWidget.contentWindow.scrollMaxY > 0) { // start the last executed command's output at the top of the screen - var elements = vimperator.buffer.evaluateXPath("//div[contains(@class, 'ex-command-output')]", multiline_output_widget.contentDocument); + var elements = vimperator.buffer.evaluateXPath("//div[contains(@class, 'ex-command-output')]", multilineOutputWidget.contentDocument); elements.snapshotItem(elements.snapshotLength - 1).scrollIntoView(true); - if (multiline_output_widget.contentWindow.scrollY >= multiline_output_widget.contentWindow.scrollMaxY) + if (multilineOutputWidget.contentWindow.scrollY >= multilineOutputWidget.contentWindow.scrollMaxY) setLine("Press ENTER or type command to continue", vimperator.commandline.HL_QUESTION); else setLine("-- More --", vimperator.commandline.HL_QUESTION); } else { - multiline_output_widget.contentWindow.scrollTo(0, content_height); + multilineOutputWidget.contentWindow.scrollTo(0, contentHeight); setLine("Press ENTER or type command to continue", vimperator.commandline.HL_QUESTION); } - multiline_output_widget.contentWindow.focus(); + multilineOutputWidget.contentWindow.focus(); // save the mode, because we need to restore it on blur() - [old_mode, old_extended_mode] = vimperator.getMode(); + [oldMode, oldExtendedMode] = vimperator.getMode(); vimperator.setMode(vimperator.modes.COMMAND_LINE, vimperator.modes.WRITE_MULTILINE, true); } @@ -224,7 +224,7 @@ vimperator.CommandLine = function () //{{{ // XXX: faster/better method? var lines = 0; - var str = multiline_input_widget.value; + var str = multilineInputWidget.value; for (var i = 0; i < str.length; i++) { if (str[i] == "\n") @@ -232,619 +232,623 @@ vimperator.CommandLine = function () //{{{ } if (lines == 0) lines = 1; - multiline_input_widget.setAttribute("rows", lines.toString()); + multilineInputWidget.setAttribute("rows", lines.toString()); } /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - this.HL_NORMAL = "hl-Normal"; - this.HL_ERRORMSG = "hl-ErrorMsg"; - this.HL_MODEMSG = "hl-ModeMsg"; - this.HL_MOREMSG = "hl-MoreMsg"; - this.HL_QUESTION = "hl-Question"; - this.HL_WARNING = "hl-Warning"; + return { - // not yet used - this.FORCE_MULTILINE = 1 << 0; - this.FORCE_SINGLELINE = 1 << 1; - this.DISALLOW_MULTILINE = 1 << 2; // if an echo() should try to use the single line, - // but output nothing when the MOW is open; when also - // FORCE_MULTILINE is given, FORCE_MULTILINE takes precedence - this.APPEND_TO_MESSAGES = 1 << 3; // will show the string in :messages + HL_NORMAL : "hl-Normal", + HL_ERRORMSG: "hl-ErrorMsg", + HL_MODEMSG : "hl-ModeMsg", + HL_MOREMSG : "hl-MoreMsg", + HL_QUESTION: "hl-Question", + HL_WARNING : "hl-Warning", - this.getCommand = function () - { - return command_widget.value; - }; + // not yet used + FORCE_MULTILINE : 1 << 0, + FORCE_SINGLELINE : 1 << 1, + DISALLOW_MULTILINE : 1 << 2, // if an echo() should try to use the single line, + // but output nothing when the MOW is open; when also + // FORCE_MULTILINE is given, FORCE_MULTILINE takes precedence + APPEND_TO_MESSAGES : 1 << 3, // will show the string in :messages - this.open = function (prompt, cmd, ext_mode) - { - // save the current prompts, we need it later if the command widget - // receives focus without calling the this.open() method - cur_prompt = prompt || ""; - cur_command = cmd || ""; - cur_extended_mode = ext_mode || null; - - history_index = UNINITIALIZED; - completion_index = UNINITIALIZED; - - // save the mode, because we need to restore it - [old_mode, old_extended_mode] = vimperator.getMode(); - vimperator.setMode(vimperator.modes.COMMAND_LINE, cur_extended_mode, true); - setHighlightGroup(this.HL_NORMAL); - setPrompt(cur_prompt); - setCommand(cur_command); - - command_widget.focus(); - }; - - // normally used when pressing esc, does not execute a command - this.close = function () - { - var res = vimperator.triggerCallback("cancel", cur_extended_mode); - history.add(this.getCommand()); - //vimperator.modes.set(old_mode, old_extended_mode); - vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible - this.clear(); - } - - // TODO: add :messages entry - // vimperator.echo uses different order of flags as it omits the hightlight group, change v.commandline.echo argument order? --mst - this.echo = function (str, highlight_group, flags) - { - var focused = document.commandDispatcher.focusedElement; - if (focused && focused == command_widget.inputField || focused == multiline_input_widget.inputField) - return false; - - highlight_group = highlight_group || this.HL_NORMAL; - - var where = setLine; - if (flags & this.FORCE_MULTILINE) - where = setMultiline; - else if (flags & this.FORCE_SINGLELINE) - where = setLine; - else if (!multiline_output_widget.collapsed) + getCommand: function () { - if (flags & this.DISALLOW_MULTILINE) - where = null; - else + return commandWidget.value; + }, + + open: function (prompt, cmd, extendedMode) + { + // save the current prompts, we need it later if the command widget + // receives focus without calling the this.open() method + currentPrompt = prompt || ""; + currentCommand = cmd || ""; + currentExtendedMode = extendedMode || null; + + historyIndex = UNINITIALIZED; + completionIndex = UNINITIALIZED; + + // save the mode, because we need to restore it + [oldMode, oldExtendedMode] = vimperator.getMode(); + vimperator.setMode(vimperator.modes.COMMAND_LINE, currentExtendedMode, true); + setHighlightGroup(this.HL_NORMAL); + setPrompt(currentPrompt); + setCommand(currentCommand); + + commandWidget.focus(); + }, + + // normally used when pressing esc, does not execute a command + close: function () + { + var res = vimperator.triggerCallback("cancel", currentExtendedMode); + history.add(this.getCommand()); + //vimperator.modes.set(oldMode, oldExtendedMode); + vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible + this.clear(); + }, + + // TODO: add :messages entry + // vimperator.echo uses different order of flags as it omits the hightlight group, change v.commandline.echo argument order? --mst + echo: function (str, highlightGroup, flags) + { + var focused = document.commandDispatcher.focusedElement; + if (focused && focused == commandWidget.inputField || focused == multilineInputWidget.inputField) + return false; + + highlightGroup = highlightGroup || this.HL_NORMAL; + + var where = setLine; + if (flags & this.FORCE_MULTILINE) + where = setMultiline; + else if (flags & this.FORCE_SINGLELINE) + where = setLine; + else if (!multilineOutputWidget.collapsed) + { + if (flags & this.DISALLOW_MULTILINE) + where = null; + else + where = setMultiline; + } + else if (/\n|/.test(str)) where = setMultiline; - } - else if (/\n|/.test(str)) - where = setMultiline; - if (where) - where(str, highlight_group); + if (where) + where(str, highlightGroup); - cur_extended_mode = null; + currentExtendedMode = null; - return true; - }; + return true; + }, - // this will prompt the user for a string - // vimperator.commandline.input("(s)ave or (o)pen the file?") - this.input = function (str) - { - // TODO: unfinished, need to find out how/if we can block the execution of code - // to make this code synchronous or at least use a callback - setLine(str, this.HL_QUESTION); - command_widget.focus(); - return "not implemented"; - }; - - // reads a multi line input and returns the string once the last line matches - // @param until_regexp - this.inputMultiline = function (until_regexp, callback_func) - { - // save the mode, because we need to restore it on blur() - [old_mode, old_extended_mode] = vimperator.getMode(); - vimperator.setMode(vimperator.modes.COMMAND_LINE, vimperator.modes.READ_MULTILINE, true); - - // save the arguments, they are needed in the event handler onEvent - multiline_regexp = until_regexp; - multiline_callback = callback_func; - - multiline_input_widget.collapsed = false; - multiline_input_widget.value = ""; - autosizeMultilineInputWidget(); - - setTimeout(function () { - multiline_input_widget.focus(); - }, 10); - }; - - this.clear = function () - { - multiline_input_widget.collapsed = true; - multiline_output_widget.collapsed = true; - completionlist.hide(); - - setLine("", this.HL_NORMAL); - }; - - this.onEvent = function (event) - { - var command = this.getCommand(); - - if (event.type == "blur") + // this will prompt the user for a string + // vimperator.commandline.input("(s)ave or (o)pen the file?") + input: function (str) { - // prevent losing focus, there should be a better way, but it just didn't work otherwise + // TODO: unfinished, need to find out how/if we can block the execution of code + // to make this code synchronous or at least use a callback + setLine(str, this.HL_QUESTION); + commandWidget.focus(); + return "not implemented"; + }, + + // reads a multi line input and returns the string once the last line matches + // @param untilRegexp + inputMultiline: function (untilRegexp, callbackFunc) + { + // save the mode, because we need to restore it on blur() + [oldMode, oldExtendedMode] = vimperator.getMode(); + vimperator.setMode(vimperator.modes.COMMAND_LINE, vimperator.modes.READ_MULTILINE, true); + + // save the arguments, they are needed in the event handler onEvent + multilineRegexp = untilRegexp; + multilineCallback = callbackFunc; + + multilineInputWidget.collapsed = false; + multilineInputWidget.value = ""; + autosizeMultilineInputWidget(); + setTimeout(function () { - if (vimperator.hasMode(vimperator.modes.COMMAND_LINE) && - !vimperator.hasMode(vimperator.modes.READ_MULTILINE) && - !vimperator.hasMode(vimperator.modes.WRITE_MULTILINE)) - command_widget.inputField.focus(); - }, 0); - } - else if (event.type == "focus") - { - if (!cur_extended_mode && event.target == command_widget.inputField) - event.target.blur(); - } - else if (event.type == "input") - { - vimperator.triggerCallback("change", cur_extended_mode, command); - } - else if (event.type == "keypress") - { - if (!cur_extended_mode) - return; + multilineInputWidget.focus(); + }, 10); + }, - var key = vimperator.events.toString(event); + clear: function () + { + multilineInputWidget.collapsed = true; + multilineOutputWidget.collapsed = true; + completionlist.hide(); - // user pressed ENTER to carry out a command - if (vimperator.events.isAcceptKey(key)) + setLine("", this.HL_NORMAL); + }, + + onEvent: function (event) + { + var command = this.getCommand(); + + if (event.type == "blur") { - var mode = cur_extended_mode; // save it here, as setMode() resets it - history.add(command); - vimperator.setMode(old_mode, old_extended_mode); - vimperator.focusContent(); - completionlist.hide(); - vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible - return vimperator.triggerCallback("submit", mode, command); + // prevent losing focus, there should be a better way, but it just didn't work otherwise + setTimeout(function () { + if (vimperator.hasMode(vimperator.modes.COMMAND_LINE) && + !vimperator.hasMode(vimperator.modes.READ_MULTILINE) && + !vimperator.hasMode(vimperator.modes.WRITE_MULTILINE)) + commandWidget.inputField.focus(); + }, 0); } - - // user pressed ESCAPE to cancel this prompt - else if (vimperator.events.isCancelKey(key)) + else if (event.type == "focus") { - var res = vimperator.triggerCallback("cancel", cur_extended_mode); - history.add(command); - vimperator.setMode(old_mode, old_extended_mode); - vimperator.focusContent(); - completionlist.hide(); - vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible - this.clear(); - return res; + if (!currentExtendedMode && event.target == commandWidget.inputField) + event.target.blur(); } - - // user pressed UP or DOWN arrow to cycle history completion - else if (key == "" || key == "") + else if (event.type == "input") { - var lines = history.get(); + vimperator.triggerCallback("change", currentExtendedMode, command); + } + else if (event.type == "keypress") + { + if (!currentExtendedMode) + return; - event.preventDefault(); - event.stopPropagation(); + var key = vimperator.events.toString(event); - // always reset the tab completion if we use up/down keys - completion_index = UNINITIALIZED; - - // save 'start' position for iterating through the history - if (history_index == UNINITIALIZED) + // user pressed ENTER to carry out a command + if (vimperator.events.isAcceptKey(key)) { - history_index = lines.length; - history_start = command; + var mode = currentExtendedMode; // save it here, as setMode() resets it + history.add(command); + vimperator.setMode(oldMode, oldExtendedMode); + vimperator.focusContent(); + completionlist.hide(); + vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible + return vimperator.triggerCallback("submit", mode, command); } - // search the history for the first item matching the current - // commandline string - while (history_index >= -1 && history_index <= lines.length) + // user pressed ESCAPE to cancel this prompt + else if (vimperator.events.isCancelKey(key)) { - key == "" ? history_index-- : history_index++; + var res = vimperator.triggerCallback("cancel", currentExtendedMode); + history.add(command); + vimperator.setMode(oldMode, oldExtendedMode); + vimperator.focusContent(); + completionlist.hide(); + vimperator.statusline.updateProgress(""); // we may have a "match x of y" visible + this.clear(); + return res; + } - // user pressed DOWN when there is no newer history item - if (history_index == lines.length) + // user pressed UP or DOWN arrow to cycle history completion + else if (key == "" || key == "") + { + var lines = history.get(); + + event.preventDefault(); + event.stopPropagation(); + + // always reset the tab completion if we use up/down keys + completionIndex = UNINITIALIZED; + + // save 'start' position for iterating through the history + if (historyIndex == UNINITIALIZED) { - setCommand(history_start); + historyIndex = lines.length; + historyStart = command; + } + + // search the history for the first item matching the current + // commandline string + while (historyIndex >= -1 && historyIndex <= lines.length) + { + key == "" ? historyIndex-- : historyIndex++; + + // user pressed DOWN when there is no newer history item + if (historyIndex == lines.length) + { + setCommand(historyStart); + return; + } + + // cannot go past history start/end + if (historyIndex <= -1) + { + historyIndex = 0; + vimperator.beep(); + break; + } + if (historyIndex >= lines.length + 1) + { + historyIndex = lines.length; + vimperator.beep(); + break; + } + + if (lines[historyIndex].indexOf(historyStart) == 0) + { + setCommand(lines[historyIndex]); + return; + } + } + } + + // user pressed TAB to get completions of a command + else if (key == "" || key == "") + { + //always reset our completion history so up/down keys will start with new values + historyIndex = UNINITIALIZED; + + // we need to build our completion list first + if (completionIndex == UNINITIALIZED) + { + completionStartIndex = 0; + + completionIndex = -1; + wildIndex = 0; + + completionPrefix = command.substring(0, commandWidget.selectionStart); + completionPostfix = command.substring(commandWidget.selectionStart); + var res = vimperator.triggerCallback("complete", currentExtendedMode, completionPrefix); + if (res) + [completionStartIndex, completions] = res; + + // sort the completion list + if (vimperator.options["wildoptions"].search(/\bsort\b/) > -1) + { + completions.sort(function (a, b) { + if (a[0] < b[0]) + return -1; + else if (a[0] > b[0]) + return 1; + else + return 0; + }); + } + } + + if (completions.length == 0) + { + vimperator.beep(); + // prevent tab from moving to the next field + event.preventDefault(); + event.stopPropagation(); return; } - // cannot go past history start/end - if (history_index <= -1) + var wim = vimperator.options["wildmode"].split(/,/); + var hasList = false; + var longest = false; + var full = false; + var wildType = wim[wildIndex++] || wim[wim.length - 1]; + if (wildType == "list" || wildType == "list:full" || wildType == "list:longest") + hasList = true; + if (wildType == "longest" || wildType == "list:longest") + longest = true; + else if (wildType == "full" || wildType == "list:full") + full = true; + + // show the list + if (hasList) { - history_index = 0; - vimperator.beep(); - break; - } - if (history_index >= lines.length + 1) - { - history_index = lines.length; - vimperator.beep(); - break; + if (completionIndex < 0) + completionlist.show(completions); + else + completionlist.show(); } - if (lines[history_index].indexOf(history_start) == 0) + if (full) { - setCommand(lines[history_index]); - return; + if (event.shiftKey) + { + completionIndex--; + if (completionIndex < -1) + completionIndex = completions.length -1; + } + else + { + completionIndex++; + if (completionIndex >= completions.length) + completionIndex = -1; + } + + vimperator.statusline.updateProgress("match " + (completionIndex + 1) + " of " + completions.length); + // if the list is hidden, this function does nothing + completionlist.selectItem(completionIndex); } - } - } - // user pressed TAB to get completions of a command - else if (key == "" || key == "") - { - //always reset our completion history so up/down keys will start with new values - history_index = UNINITIALIZED; - // we need to build our completion list first - if (completion_index == UNINITIALIZED) - { - completion_start_index = 0; - - completion_index = -1; - wild_index = 0; - - completion_prefix = command.substring(0, command_widget.selectionStart); - completion_postfix = command.substring(command_widget.selectionStart); - var res = vimperator.triggerCallback("complete", cur_extended_mode, completion_prefix); - if (res) - [completion_start_index, completions] = res; - - // sort the completion list - if (vimperator.options["wildoptions"].search(/\bsort\b/) > -1) + if (completionIndex == -1 && !longest) // wrapped around matches, reset command line { - completions.sort(function (a, b) { - if (a[0] < b[0]) - return -1; - else if (a[0] > b[0]) - return 1; - else - return 0; - }); + if (full && completions.length > 1) + { + setCommand(completionPrefix + completionPostfix); + } + } + else + { + if (longest && completions.length > 1) + var compl = vimperator.completion.getLongestSubstring(); + else if (full) + var compl = completions[completionIndex][0]; + else if (completions.length == 1) + var compl = completions[0][0]; + if (compl) + { + setCommand(command.substring(0, completionStartIndex) + compl + completionPostfix); + commandWidget.selectionStart = commandWidget.selectionEnd = completionStartIndex + compl.length; + + // Start a new completion in the next iteration. Useful for commands like :source + // RFC: perhaps the command can indicate whether the completion should be restarted + // Needed for :source to grab another set of completions after a file/directory has been filled out + if (completions.length == 1 && !full) + completionIndex = UNINITIALIZED; + } } - } - if (completions.length == 0) - { - vimperator.beep(); // prevent tab from moving to the next field event.preventDefault(); event.stopPropagation(); - return; } - - var wim = vimperator.options["wildmode"].split(/,/); - var has_list = false; - var longest = false; - var full = false; - var wildtype = wim[wild_index++] || wim[wim.length - 1]; - if (wildtype == "list" || wildtype == "list:full" || wildtype == "list:longest") - has_list = true; - if (wildtype == "longest" || wildtype == "list:longest") - longest = true; - else if (wildtype == "full" || wildtype == "list:full") - full = true; - - // show the list - if (has_list) + else if (key == "") { - if (completion_index < 0) - completionlist.show(completions); - else - completionlist.show(); - } + // reset the tab completion + completionIndex = historyIndex = UNINITIALIZED; - if (full) - { - if (event.shiftKey) + // and blur the command line if there is no text left + if (command.length == 0) { - completion_index--; - if (completion_index < -1) - completion_index = completions.length -1; - } - else - { - completion_index++; - if (completion_index >= completions.length) - completion_index = -1; - } - - vimperator.statusline.updateProgress("match " + (completion_index + 1) + " of " + completions.length); - // if the list is hidden, this function does nothing - completionlist.selectItem(completion_index); - } - - - if (completion_index == -1 && !longest) // wrapped around matches, reset command line - { - if (full && completions.length > 1) - { - setCommand(completion_prefix + completion_postfix); + vimperator.triggerCallback("cancel", currentExtendedMode); + vimperator.setMode(oldMode, oldExtendedMode); + vimperator.focusContent(); + this.clear(); } } - else + else // any other key { - if (longest && completions.length > 1) - var compl = vimperator.completion.get_longest_substring(); - else if (full) - var compl = completions[completion_index][0]; - else if (completions.length == 1) - var compl = completions[0][0]; - if (compl) - { - setCommand(command.substring(0, completion_start_index) + compl + completion_postfix); - command_widget.selectionStart = command_widget.selectionEnd = completion_start_index + compl.length; - - // Start a new completion in the next iteration. Useful for commands like :source - // RFC: perhaps the command can indicate whether the completion should be restarted - // Needed for :source to grab another set of completions after a file/directory has been filled out - if (completions.length == 1 && !full) - completion_index = UNINITIALIZED; - } - } - - // prevent tab from moving to the next field - event.preventDefault(); - event.stopPropagation(); - } - else if (key == "") - { - // reset the tab completion - completion_index = history_index = UNINITIALIZED; - - // and blur the command line if there is no text left - if (command.length == 0) - { - vimperator.triggerCallback("cancel", cur_extended_mode); - vimperator.setMode(old_mode, old_extended_mode); - vimperator.focusContent(); - this.clear(); + // reset the tab completion + completionIndex = historyIndex = UNINITIALIZED; } } - else // any other key - { - // reset the tab completion - completion_index = history_index = UNINITIALIZED; - } - } - } + }, - this.onMultilineInputEvent = function (event) - { - if (event.type == "keypress") + onMultilineInputEvent: function (event) { + if (event.type == "keypress") + { + var key = vimperator.events.toString(event); + if (vimperator.events.isAcceptKey(key)) + { + var text = multilineInputWidget.value.substr(0, multilineInputWidget.selectionStart); + if (text.match(multilineRegexp)) + { + text = text.replace(multilineRegexp, ""); + vimperator.setMode(oldMode, oldExtendedMode); + multilineInputWidget.collapsed = true; + multilineCallback.call(this, text); + } + } + else if (vimperator.events.isCancelKey(key)) + { + vimperator.setMode(oldMode, oldExtendedMode); + multilineInputWidget.collapsed = true; + } + } + else if (event.type == "blur") + { + if (vimperator.hasMode(vimperator.modes.READ_MULTILINE)) + setTimeout(function () { multilineInputWidget.inputField.focus(); }, 0); + } + else if (event.type == "input") + { + autosizeMultilineInputWidget(); + } + }, + + // FIXME: if 'more' is set and the MOW is not scrollable we should still + // allow a down motion after an up rather than closing + onMultilineOutputEvent: function (event) + { + var win = multilineOutputWidget.contentWindow; + + var showMoreHelpPrompt = false; + var showMorePrompt = false; + var closeWindow = false; + var passEvent = false; + + function isScrollable() { return !win.scrollMaxY == 0; } + + function atEnd() { return win.scrollY / win.scrollMaxY >= 1; } + var key = vimperator.events.toString(event); - if (vimperator.events.isAcceptKey(key)) + + switch (key) { - var text = multiline_input_widget.value.substr(0, multiline_input_widget.selectionStart); - if (text.match(multiline_regexp)) - { - text = text.replace(multiline_regexp, ""); - vimperator.setMode(old_mode, old_extended_mode); - multiline_input_widget.collapsed = true; - multiline_callback.call(this, text); - } + case ":": + vimperator.commandline.open(":", "", vimperator.modes.EX); + return; + + // down a line + case "j": + case "": + if (vimperator.options["more"] && isScrollable()) + win.scrollByLines(1); + else + passEvent = true; + break; + + case "": + case "": + case "": + if (vimperator.options["more"] && isScrollable() && !atEnd()) + win.scrollByLines(1); + else + closeWindow = true; // don't propagate the event for accept keys + break; + + // up a line + case "k": + case "": + case "": + if (vimperator.options["more"] && isScrollable()) + win.scrollByLines(-1); + else if (vimperator.options["more"] && !isScrollable()) + showMorePrompt = true; + else + passEvent = true; + break; + + // half page down + case "d": + if (vimperator.options["more"] && isScrollable()) + win.scrollBy(0, win.innerHeight / 2); + else + passEvent = true; + break; + + case "": + if (event.originalTarget.className == "hl-URL buffer-list") + { + vimperator.tabs.select(parseInt(event.originalTarget.parentNode.parentNode.firstChild.textContent, 10) - 1); + closeWindow = true; + break; + } + else if (event.originalTarget.localName.toLowerCase() == "a") + { + vimperator.open(event.originalTarget.textContent); + break; + } + case "": // for those not owning a 3-button mouse + case "": + if (event.originalTarget.localName.toLowerCase() == "a") + { + var where = /\btabopen\b/.test(vimperator.options["activate"]) ? + vimperator.NEW_TAB : vimperator.NEW_BACKGROUND_TAB; + vimperator.open(event.originalTarget.textContent, where); + } + break; + + // let firefox handle those to select table cells or show a context menu + case "": + case "": + case "": + break; + + // XXX: what's that for? --mst + case "": + if (/^(end|more(-help)?)-prompt$/.test(event.target.id)) + ; // fall through + else + break; + + // page down + case "f": + if (vimperator.options["more"] && isScrollable()) + win.scrollByPages(1); + else + passEvent = true; + break; + + case "": + case "": + if (vimperator.options["more"] && isScrollable() && !atEnd()) + win.scrollByPages(1); + else + passEvent = true; + break; + + // half page up + case "u": + // if (more and scrollable) + if (vimperator.options["more"] && isScrollable()) + win.scrollBy(0, -(win.innerHeight / 2)); + else + passEvent = true; + break; + + // page up + case "b": + if (vimperator.options["more"] && isScrollable()) + win.scrollByPages(-1); + else if (vimperator.options["more"] && !isScrollable()) + showMorePrompt = true; + else + passEvent = true; + break; + + case "": + if (vimperator.options["more"] && isScrollable()) + win.scrollByPages(-1); + else + passEvent = true; + break; + + // top of page + case "g": + if (vimperator.options["more"] && isScrollable()) + win.scrollTo(0, 0); + else if (vimperator.options["more"] && !isScrollable()) + showMorePrompt = true; + else + passEvent = true; + break; + + // bottom of page + case "G": + if (vimperator.options["more"] && isScrollable() && !atEnd()) + win.scrollTo(0, win.scrollMaxY); + else + passEvent = true; + break; + + // copy text to clipboard + case "": + vimperator.copyToClipboard(win.getSelection()); + break; + + // close the window + case "q": + closeWindow = true; + break; + + // unmapped key + default: + if (!vimperator.options["more"] || !isScrollable() || atEnd() || vimperator.events.isCancelKey(key)) + passEvent = true; + else + showMoreHelpPrompt = true; } - else if (vimperator.events.isCancelKey(key)) + + if (passEvent || closeWindow) { - vimperator.setMode(old_mode, old_extended_mode); - multiline_input_widget.collapsed = true; + vimperator.setMode(vimperator.modes.NORMAL); + vimperator.focusContent(); + this.clear(); + + if (passEvent) + vimperator.events.onKeyPress(event); } - } - else if (event.type == "blur") + else // set update the prompt string + { + if (showMoreHelpPrompt) + setLine("-- More -- SPACE/d/j: screen/page/line down, b/u/k: up, q: quit", this.HL_MOREMSG); + else if (showMorePrompt || (vimperator.options["more"] && isScrollable() && !atEnd())) + setLine("-- More --", this.HL_MOREMSG); + else + setLine("Press ENTER or type command to continue", this.HL_QUESTION); + } + }, + + // it would be better if we had a destructor in javascript ... + destroy: function () { - if (vimperator.hasMode(vimperator.modes.READ_MULTILINE)) - setTimeout(function () { multiline_input_widget.inputField.focus(); }, 0); - } - else if (event.type == "input") - { - autosizeMultilineInputWidget(); - } - } - - // FIXME: if 'more' is set and the MOW is not scrollable we should still - // allow a down motion after an up rather than closing - this.onMultilineOutputEvent = function (event) - { - var win = multiline_output_widget.contentWindow; - - var show_more_help_prompt = false; - var show_more_prompt = false; - var close_window = false; - var pass_event = false; - - function isScrollable() { return !win.scrollMaxY == 0; } - - function atEnd() { return win.scrollY / win.scrollMaxY >= 1; } - - var key = vimperator.events.toString(event); - - switch (key) - { - case ":": - vimperator.commandline.open(":", "", vimperator.modes.EX); - return; - - // down a line - case "j": - case "": - if (vimperator.options["more"] && isScrollable()) - win.scrollByLines(1); - else - pass_event = true; - break; - - case "": - case "": - case "": - if (vimperator.options["more"] && isScrollable() && !atEnd()) - win.scrollByLines(1); - else - close_window = true; // don't propagate the event for accept keys - break; - - // up a line - case "k": - case "": - case "": - if (vimperator.options["more"] && isScrollable()) - win.scrollByLines(-1); - else if (vimperator.options["more"] && !isScrollable()) - show_more_prompt = true; - else - pass_event = true; - break; - - // half page down - case "d": - if (vimperator.options["more"] && isScrollable()) - win.scrollBy(0, win.innerHeight / 2); - else - pass_event = true; - break; - - case "": - if (event.originalTarget.className == "hl-URL buffer-list") - { - vimperator.tabs.select(parseInt(event.originalTarget.parentNode.parentNode.firstChild.textContent, 10) - 1); - close_window = true; - break; - } - else if (event.originalTarget.localName.toLowerCase() == "a") - { - vimperator.open(event.originalTarget.textContent); - break; - } - case "": // for those not owning a 3-button mouse - case "": - if (event.originalTarget.localName.toLowerCase() == "a") - { - var where = /\btabopen\b/.test(vimperator.options["activate"]) ? - vimperator.NEW_TAB : vimperator.NEW_BACKGROUND_TAB; - vimperator.open(event.originalTarget.textContent, where); - } - break; - - // let firefox handle those to select table cells or show a context menu - case "": - case "": - case "": - break; - - // XXX: what's that for? --mst - case "": - if (/^(end|more(-help)?)-prompt$/.test(event.target.id)) - ; // fall through - else - break; - - // page down - case "f": - if (vimperator.options["more"] && isScrollable()) - win.scrollByPages(1); - else - pass_event = true; - break; - - case "": - case "": - if (vimperator.options["more"] && isScrollable() && !atEnd()) - win.scrollByPages(1); - else - pass_event = true; - break; - - // half page up - case "u": - // if (more and scrollable) - if (vimperator.options["more"] && isScrollable()) - win.scrollBy(0, -(win.innerHeight / 2)); - else - pass_event = true; - break; - - // page up - case "b": - if (vimperator.options["more"] && isScrollable()) - win.scrollByPages(-1); - else if (vimperator.options["more"] && !isScrollable()) - show_more_prompt = true; - else - pass_event = true; - break; - - case "": - if (vimperator.options["more"] && isScrollable()) - win.scrollByPages(-1); - else - pass_event = true; - break; - - // top of page - case "g": - if (vimperator.options["more"] && isScrollable()) - win.scrollTo(0, 0); - else if (vimperator.options["more"] && !isScrollable()) - show_more_prompt = true; - else - pass_event = true; - break; - - // bottom of page - case "G": - if (vimperator.options["more"] && isScrollable() && !atEnd()) - win.scrollTo(0, win.scrollMaxY); - else - pass_event = true; - break; - - // copy text to clipboard - case "": - vimperator.copyToClipboard(win.getSelection()); - break; - - // close the window - case "q": - close_window = true; - break; - - // unmapped key - default: - if (!vimperator.options["more"] || !isScrollable() || atEnd() || vimperator.events.isCancelKey(key)) - pass_event = true; - else - show_more_help_prompt = true; + history.save(); } - if (pass_event || close_window) - { - vimperator.setMode(vimperator.modes.NORMAL); - vimperator.focusContent(); - this.clear(); - - if (pass_event) - vimperator.events.onKeyPress(event); - } - else // set update the prompt string - { - if (show_more_help_prompt) - setLine("-- More -- SPACE/d/j: screen/page/line down, b/u/k: up, q: quit", this.HL_MOREMSG); - else if (show_more_prompt || (vimperator.options["more"] && isScrollable() && !atEnd())) - setLine("-- More --", this.HL_MOREMSG); - else - setLine("Press ENTER or type command to continue", this.HL_QUESTION); - } - } - - // it would be better if we had a destructor in javascript ... - this.destroy = function () - { - history.save(); - } + }; //}}} -} //}}} +}; //}}} /** * The list which is used for the completion box, the preview window and the buffer preview window @@ -859,36 +863,36 @@ vimperator.InformationList = function (id, options) //{{{ /////////////////////////////////////////////////////////////////////////////{{{ const CONTEXT_LINES = 3; - var max_items = 10; - var min_items = 1; - var incremental_fill = true; // make display faster, but does not show scrollbar + var maxItems = 10; + var minItems = 1; + var incrementalFill = true; // make display faster, but does not show scrollbar if (options) { - if (options.max_items) max_items = options.max_items; - if (options.min_items) min_items = options.min_items; - if (options.incremental_fill) incremental_fill = options.incremental_fill; + if (options.maxItems) maxItems = options.maxItems; + if (options.minItems) minItems = options.minItems; + if (options.incrementalFill) incrementalFill = options.incrementalFill; } var widget = document.getElementById(id); var completions = null; // a reference to the Array of completions - var list_offset = 0; // how many items is the displayed list shifted from the internal tab index - var list_index = 0; // list_offset + list_index = completions[item] + var listOffset = 0; // how many items is the displayed list shifted from the internal tab index + var listIndex = 0; // listOffset + listIndex = completions[item] // add a single completion item to the list - function addItem(completion_item, at_beginning) + function addItem(completionItem, atBeginning) { var item = document.createElement("listitem"); var cell1 = document.createElement("listcell"); var cell2 = document.createElement("listcell"); - cell1.setAttribute("label", completion_item[0]); - cell2.setAttribute("label", completion_item[1]); + cell1.setAttribute("label", completionItem[0]); + cell2.setAttribute("label", completionItem[1]); cell2.setAttribute("style", "color:green; font-family: sans"); item.appendChild(cell1); item.appendChild(cell2); - if (at_beginning == true) + if (atBeginning == true) { var items = widget.getElementsByTagName("listitem"); if (items.length > 0) @@ -903,7 +907,7 @@ vimperator.InformationList = function (id, options) //{{{ /** * uses the entries in completions to fill the listbox * - * @param startindex: start at this index and show max_items + * @param startindex: start at this index and show maxItems * @returns the number of items */ function fill(startindex) @@ -917,7 +921,7 @@ vimperator.InformationList = function (id, options) //{{{ widget.removeChild(items[0]); } - if (!incremental_fill) + if (!incrementalFill) { for (i in completions) addItem(completions[i], false); @@ -925,15 +929,15 @@ vimperator.InformationList = function (id, options) //{{{ } // find start index - if (startindex + max_items > complength) - startindex = complength - max_items; + if (startindex + maxItems > complength) + startindex = complength - maxItems; if (startindex < 0) startindex = 0; - list_offset = startindex; - list_index = -1; + listOffset = startindex; + listIndex = -1; - for (var i = startindex; i < complength && i < startindex + max_items; i++) + for (var i = startindex; i < complength && i < startindex + maxItems; i++) { addItem(completions[i], false); } @@ -945,115 +949,119 @@ vimperator.InformationList = function (id, options) //{{{ ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - /** - * Show the completion list window - * - * @param compl: if null, only show the list with current entries, otherwise - * use entries of 'compl' to fill the list. - * Required format: [["left", "right"], ["another"], ["completion"]] - */ - this.show = function (compl) - { - //max_items = vimperator.options["previewheight"]; + return { - if (compl) + /** + * Show the completion list window + * + * @param compl: if null, only show the list with current entries, otherwise + * use entries of 'compl' to fill the list. + * Required format: [["left", "right"], ["another"], ["completion"]] + */ + show: function (compl) { - completions = compl; - fill(0); - } + //maxItems = vimperator.options["previewheight"]; - var length = completions.length; - if (length > max_items) - length = max_items; - if (length >= min_items) - { - widget.setAttribute("rows", length.toString()); - widget.hidden = false; - return true; - } - else + if (compl) + { + completions = compl; + fill(0); + } + + var length = completions.length; + if (length > maxItems) + length = maxItems; + if (length >= minItems) + { + widget.setAttribute("rows", length.toString()); + widget.hidden = false; + return true; + } + else + { + widget.hidden = true; + return false; + } + }, + + hide: function () { widget.hidden = true; - return false; - } - } + }, - this.hide = function () - { - widget.hidden = true; - } - - this.visible = function () - { - return !widget.hidden; - } - - /** - * select index, refill list if necessary - */ - this.selectItem = function (index) - { - if (widget.hidden) - return; - - if (!incremental_fill) + visible: function () { - widget.selectedIndex = index; - return; - } + return !widget.hidden; + }, - // find start index - var new_offset = 0; - if (index >= list_offset + max_items - CONTEXT_LINES) - new_offset = index - max_items + CONTEXT_LINES + 1; - else if (index <= list_offset + CONTEXT_LINES) - new_offset = index - CONTEXT_LINES; - else - new_offset = list_offset; - - if (new_offset + max_items > completions.length) - new_offset = completions.length - max_items; - if (new_offset < 0) - new_offset = 0; - - // for speed reason: just remove old item, and add the new one at the end of the list - var items = widget.getElementsByTagName("listitem"); - if (new_offset == list_offset + 1) + /** + * select index, refill list if necessary + */ + selectItem: function (index) { - widget.removeChild(items[0]); - addItem(completions[index + CONTEXT_LINES], false); - } - else if (new_offset == list_offset - 1) - { - widget.removeChild(items[items.length-1]); - addItem(completions[index - CONTEXT_LINES], true); - } - else if (new_offset == list_offset) - { - // do nothing - } - else - fill(new_offset); + if (widget.hidden) + return; - list_offset = new_offset; - widget.selectedIndex = index - list_offset; - } + if (!incrementalFill) + { + widget.selectedIndex = index; + return; + } - this.onEvent = function (event) - { - var listcells = document.getElementsByTagName("listcell"); - // 2 columns for now, use the first column - var index = (widget.selectedIndex * 2) + 0; - var val = listcells[index].getAttribute("label"); - if (val && event.button == 0 && event.type == "dblclick") // left double click - vimperator.open(val); - else if (val && event.button == 1) // middle click - vimperator.open(val, vimperator.NEW_TAB); - else - return false; - } + // find start index + var newOffset = 0; + if (index >= listOffset + maxItems - CONTEXT_LINES) + newOffset = index - maxItems + CONTEXT_LINES + 1; + else if (index <= listOffset + CONTEXT_LINES) + newOffset = index - CONTEXT_LINES; + else + newOffset = listOffset; + + if (newOffset + maxItems > completions.length) + newOffset = completions.length - maxItems; + if (newOffset < 0) + newOffset = 0; + + // for speed reason: just remove old item, and add the new one at the end of the list + var items = widget.getElementsByTagName("listitem"); + if (newOffset == listOffset + 1) + { + widget.removeChild(items[0]); + addItem(completions[index + CONTEXT_LINES], false); + } + else if (newOffset == listOffset - 1) + { + widget.removeChild(items[items.length-1]); + addItem(completions[index - CONTEXT_LINES], true); + } + else if (newOffset == listOffset) + { + // do nothing + } + else + fill(newOffset); + + listOffset = newOffset; + widget.selectedIndex = index - listOffset; + }, + + onEvent: function (event) + { + var listcells = document.getElementsByTagName("listcell"); + // 2 columns for now, use the first column + var index = (widget.selectedIndex * 2) + 0; + var val = listcells[index].getAttribute("label"); + if (val && event.button == 0 && event.type == "dblclick") // left double click + vimperator.open(val); + else if (val && event.button == 1) // middle click + vimperator.open(val, vimperator.NEW_TAB); + else + return false; + } + + }; //}}} -} //}}} +}; //}}} vimperator.StatusLine = function () //{{{ { @@ -1061,154 +1069,158 @@ vimperator.StatusLine = function () //{{{ ////////////////////// PRIVATE SECTION ///////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - var status_bar = document.getElementById("status-bar"); + var statusBar = document.getElementById("status-bar"); // our status bar fields - var statusline_widget = document.getElementById("vimperator-statusline"); - var url_widget = document.getElementById("vimperator-statusline-field-url"); - var inputbuffer_widget = document.getElementById("vimperator-statusline-field-inputbuffer"); - var progress_widget = document.getElementById("vimperator-statusline-field-progress"); - var tabcount_widget = document.getElementById("vimperator-statusline-field-tabcount"); - var bufferposition_widget = document.getElementById("vimperator-statusline-field-bufferposition"); + var statuslineWidget = document.getElementById("vimperator-statusline"); + var urlWidget = document.getElementById("vimperator-statusline-field-url"); + var inputBufferWidget = document.getElementById("vimperator-statusline-field-inputbuffer"); + var progressWidget = document.getElementById("vimperator-statusline-field-progress"); + var tabCountWidget = document.getElementById("vimperator-statusline-field-tabcount"); + var bufferPositionWidget = document.getElementById("vimperator-statusline-field-bufferposition"); /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - this.setClass = function (type) - { - var highlight_group; + return { - switch (type) + setClass: function (type) { - case "secure": - highlight_group = "hl-StatusLineSecure"; - break; - case "broken": - highlight_group = "hl-StatusLineBroken"; - break; - case "insecure": - highlight_group = "hl-StatusLine"; - break; - } + var highlightGroup; - status_bar.setAttribute("class", "chromeclass-status " + highlight_group); - }; - - // update all fields of the statusline - this.update = function () - { - this.updateUrl(); - this.updateInputBuffer(); - this.updateProgress(); - this.updateTabCount(); - this.updateBufferPosition(); - } - - // if "url" is ommited, build a usable string for the URL - this.updateUrl = function (url) - { - if (typeof url == "string") - { - url_widget.value = url; - return; - } - - url = vimperator.buffer.URL; - - // make it even more vim-like - if (url == "about:blank") - { - var title = vimperator.buffer.title; - - if (title == "Vimperator Help") - url = "[Help]"; - else if (!title) - url = "[No Name]"; - } - - var sh = getWebNavigation().sessionHistory; - var modified = ""; - if (sh.index > 0) - modified += "+"; - if (sh.index < sh.count -1) - modified += "-"; - - if (modified) - url += " [" + modified + "]" - - url_widget.value = url; - }; - - this.updateInputBuffer = function (buffer) - { - if (!buffer || typeof buffer != "string") - buffer = ""; - - inputbuffer_widget.value = buffer; - }; - - this.updateProgress = function (progress) - { - if (!progress) - progress = ""; - - if (typeof progress == "string") - progress_widget.value = progress; - else if (typeof progress == "number") - { - var progress_str = ""; - if (progress <= 0) - progress_str = "[ Loading... ]"; - else if (progress < 1) + switch (type) { - progress_str = "["; - var done = Math.floor(progress * 20); - for (var i = 0; i < done; i++) - progress_str += "="; - - progress_str += ">"; - - for (var i = 19; i > done; i--) - progress_str += " "; - - progress_str += "]"; + case "secure": + highlightGroup = "hl-StatusLineSecure"; + break; + case "broken": + highlightGroup = "hl-StatusLineBroken"; + break; + case "insecure": + highlightGroup = "hl-StatusLine"; + break; } - progress_widget.value = progress_str; - } - }; - // you can omit either of the 2 arguments - this.updateTabCount = function (cur_index, total_tabs) - { - if (!cur_index || typeof cur_index != "number") - cur_index = vimperator.tabs.index() + 1; - if (!total_tabs || typeof cur_index != "number") - total_tabs = vimperator.tabs.count(); + statusBar.setAttribute("class", "chromeclass-status " + highlightGroup); + }, - tabcount_widget.value = "[" + cur_index + "/" + total_tabs + "]"; - }; - - // percent is given between 0 and 1 - this.updateBufferPosition = function (percent) - { - if (!percent || typeof percent != "number") + // update all fields of the statusline + update: function () { - var win = document.commandDispatcher.focusedWindow; - percent = win.scrollMaxY == 0 ? -1 : win.scrollY / win.scrollMaxY; + this.updateUrl(); + this.updateInputBuffer(); + this.updateProgress(); + this.updateTabCount(); + this.updateBufferPosition(); + }, + + // if "url" is ommited, build a usable string for the URL + updateUrl: function (url) + { + if (typeof url == "string") + { + urlWidget.value = url; + return; + } + + url = vimperator.buffer.URL; + + // make it even more vim-like + if (url == "about:blank") + { + var title = vimperator.buffer.title; + + if (title == "Vimperator Help") + url = "[Help]"; + else if (!title) + url = "[No Name]"; + } + + var sh = getWebNavigation().sessionHistory; + var modified = ""; + if (sh.index > 0) + modified += "+"; + if (sh.index < sh.count -1) + modified += "-"; + + if (modified) + url += " [" + modified + "]"; + + urlWidget.value = url; + }, + + updateInputBuffer: function (buffer) + { + if (!buffer || typeof buffer != "string") + buffer = ""; + + inputBufferWidget.value = buffer; + }, + + updateProgress: function (progress) + { + if (!progress) + progress = ""; + + if (typeof progress == "string") + progressWidget.value = progress; + else if (typeof progress == "number") + { + var progressStr = ""; + if (progress <= 0) + progressStr = "[ Loading... ]"; + else if (progress < 1) + { + progressStr = "["; + var done = Math.floor(progress * 20); + for (var i = 0; i < done; i++) + progressStr += "="; + + progressStr += ">"; + + for (var i = 19; i > done; i--) + progressStr += " "; + + progressStr += "]"; + } + progressWidget.value = progressStr; + } + }, + + // you can omit either of the 2 arguments + updateTabCount: function (currentIndex, totalTabs) + { + if (!currentIndex || typeof currentIndex != "number") + currentIndex = vimperator.tabs.index() + 1; + if (!totalTabs || typeof currentIndex != "number") + totalTabs = vimperator.tabs.count; + + tabCountWidget.value = "[" + currentIndex + "/" + totalTabs + "]"; + }, + + // percent is given between 0 and 1 + updateBufferPosition: function (percent) + { + if (!percent || typeof percent != "number") + { + var win = document.commandDispatcher.focusedWindow; + percent = win.scrollMaxY == 0 ? -1 : win.scrollY / win.scrollMaxY; + } + + var bufferPositionStr = ""; + percent = Math.round(percent * 100); + if (percent < 0) bufferPositionStr = "All"; + else if (percent == 0) bufferPositionStr = "Top"; + else if (percent < 10) bufferPositionStr = " " + percent + "%"; + else if (percent >= 100) bufferPositionStr = "Bot"; + else bufferPositionStr = percent + "%"; + + bufferPositionWidget.value = bufferPositionStr; } - var bufferposition_str = ""; - percent = Math.round(percent*100); - if (percent < 0) bufferposition_str = "All"; - else if (percent == 0) bufferposition_str = "Top"; - else if (percent < 10) bufferposition_str = " " + percent + "%"; - else if (percent >= 100) bufferposition_str = "Bot"; - else bufferposition_str = percent + "%"; - - bufferposition_widget.value = bufferposition_str; }; //}}} -} //}}} +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/util.js b/content/util.js index 2fb5f167..1eee1f1c 100644 --- a/content/util.js +++ b/content/util.js @@ -26,7 +26,8 @@ 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.util = { +vimperator.util = { //{{{ + escapeHTML: function (str) { // XXX: the following code is _much_ slower than a simple .replace() @@ -39,11 +40,11 @@ vimperator.util = { }, // TODO: use :highlight color groups - // if "process_strings" is true, any passed strings will be surrounded by " and + // if "processStrings" is true, any passed strings will be surrounded by " and // any line breaks are displayed as \n - colorize: function (arg, process_strings) + colorize: function (arg, processStrings) { - var type = typeof(arg); + var type = typeof arg; // some objects like window.JSON or getBrowsers()._browsers need the try/catch try @@ -54,7 +55,7 @@ vimperator.util = { } else if (type == "string") { - if (process_strings) + if (processStrings) arg = '"' + vimperator.util.escapeHTML(arg.replace(/\n/, "\\n")) + '"'; return "" + arg + ""; @@ -97,7 +98,7 @@ vimperator.util = { begin: for (var url = 0; url < urls.length; url++) { - var new_url = vimperator.buffer.URL; + var newURL = vimperator.buffer.URL; var matches; // strip each 'URL' - makes things simpler later on @@ -108,13 +109,13 @@ vimperator.util = { if (matches = urls[url].match(/^(?:\.$|\.\/(\S*))/)) { var tail = matches[1] || ""; - urls[url] = new_url.replace(/(.+\/)[^\/]*/, "$1" + tail); // NOTE: escape / in character sets so as not to break Vim syntax highlighting + urls[url] = newURL.replace(/(.+\/)[^\/]*/, "$1" + tail); // NOTE: escape / in character sets so as not to break Vim syntax highlighting continue; } else if (matches = urls[url].match(/^(?:\.\.$|\.\.\/(\S*))/)) { var tail = matches[1] || ""; - urls[url] = new_url.replace(/(.+\/)[^\/]*/, "$1../" + tail); + urls[url] = newURL.replace(/(.+\/)[^\/]*/, "$1../" + tail); continue; } else if (matches = urls[url].match(/^(?:\.\.\.$|\.\.\.\/(\S*))/)) @@ -142,18 +143,18 @@ vimperator.util = { // like the comments below ;-) // check if the first word is a search engine - var search_url = vimperator.bookmarks.getSearchURL(text, alias); - if (search_url/* && search_url.length >= 1*/) + var searchURL = vimperator.bookmarks.getSearchURL(text, alias); + if (searchURL/* && searchURL.length >= 1*/) { - urls[url] = search_url; + urls[url] = searchURL; continue; } else // the first word was not a search engine, search for the whole string in the default engine { - search_url = vimperator.bookmarks.getSearchURL(urls[url], null); - if (search_url/* && search_url.length >= 1*/) + searchURL = vimperator.bookmarks.getSearchURL(urls[url], null); + if (searchURL/* && searchURL.length >= 1*/) { - urls[url] = search_url; + urls[url] = searchURL; continue; } } @@ -206,6 +207,7 @@ vimperator.util = { return strNum[0] + " " + unitVal[unitIndex]; } -}; + +}; //}}} // vim: set fdm=marker sw=4 ts=4 et: diff --git a/content/vimperator.js b/content/vimperator.js index d28d5d9e..77a589a5 100644 --- a/content/vimperator.js +++ b/content/vimperator.js @@ -52,32 +52,32 @@ const vimperator = (function () //{{{ EXTENDED_HINT: 1 << 18, ALWAYS_HINT: 1 << 19, MENU: 1 << 20 // a popupmenu is active - } + }; - var mode_messages = {}; - mode_messages[modes.NORMAL] = ""; - mode_messages[modes.INSERT] = "INSERT"; - mode_messages[modes.VISUAL] = "VISUAL"; - mode_messages[modes.HINTS] = "HINTS"; - mode_messages[modes.ESCAPE_ONE_KEY] = "escape one key"; - mode_messages[modes.ESCAPE_ALL_KEYS] = "escape all keys"; - mode_messages[modes.ESCAPE_ONE_KEY | modes.ESCAPE_ALL_KEYS] = "pass one key"; - mode_messages[modes.QUICK_HINT] = "quick"; - mode_messages[modes.EXTENDED_HINT] = "extended"; - mode_messages[modes.ALWAYS_HINT] = "always"; - //mode_messages[modes.MENU] = "menu"; // not a user visible mode + var modeMessages = {}; + modeMessages[modes.NORMAL] = ""; + modeMessages[modes.INSERT] = "INSERT"; + modeMessages[modes.VISUAL] = "VISUAL"; + modeMessages[modes.HINTS] = "HINTS"; + modeMessages[modes.ESCAPE_ONE_KEY] = "escape one key"; + modeMessages[modes.ESCAPE_ALL_KEYS] = "escape all keys"; + modeMessages[modes.ESCAPE_ONE_KEY | modes.ESCAPE_ALL_KEYS] = "pass one key"; + modeMessages[modes.QUICK_HINT] = "quick"; + modeMessages[modes.EXTENDED_HINT] = "extended"; + modeMessages[modes.ALWAYS_HINT] = "always"; + //modeMessages[modes.MENU] = "menu"; // not a user visible mode var mode = modes.NORMAL; - var extended_mode = modes.NONE; + var extendedMode = modes.NONE; var callbacks = []; // our services - var sound_service = Components.classes["@mozilla.org/sound;1"] + var soundService = Components.classes["@mozilla.org/sound;1"] .getService(Components.interfaces.nsISound); - var console_service = Components.classes["@mozilla.org/consoleservice;1"] + var consoleService = Components.classes["@mozilla.org/consoleservice;1"] .getService(Components.interfaces.nsIConsoleService); - var environment_service = Components.classes["@mozilla.org/process/environment;1"] + var environmentService = Components.classes["@mozilla.org/process/environment;1"] .getService(Components.interfaces.nsIEnvironment); function showMode() @@ -85,23 +85,23 @@ const vimperator = (function () //{{{ if (!vimperator.options["showmode"]) return; - var str_mode = mode_messages[mode]; - var str_extended = mode_messages[extended_mode]; - if (!str_mode && !str_extended) + var strMode = modeMessages[mode]; + var strExtended = modeMessages[extendedMode]; + if (!strMode && !strExtended) { vimperator.echo(""); return; } - if (str_mode && str_extended) - str_extended = " (" + str_extended + ")"; + if (strMode && strExtended) + strExtended = " (" + strExtended + ")"; else { - str_extended = "(" + str_extended + ")"; - str_mode = ""; + strExtended = "(" + strExtended + ")"; + strMode = ""; } - vimperator.echo("-- " + str_mode + str_extended + " --"); + vimperator.echo("-- " + strMode + strExtended + " --"); } /////////////////////////////////////////////////////////////////////////////}}} @@ -154,7 +154,7 @@ const vimperator = (function () //{{{ getMode: function () { - return [mode, extended_mode]; + return [mode, extendedMode]; }, // set current mode @@ -165,10 +165,10 @@ const vimperator = (function () //{{{ if (main) { mode = main; - extended_mode = vimperator.modes.NONE; + extendedMode = vimperator.modes.NONE; } if (typeof extended === "number") - extended_mode = extended; + extendedMode = extended; if (!silent) showMode(); @@ -178,7 +178,7 @@ const vimperator = (function () //{{{ // extended mode hasMode: function (whichmode) { - return ((mode & whichmode) || (extended_mode & whichmode) > 0) ? true : false; + return ((mode & whichmode) || (extendedMode & whichmode) > 0) ? true : false; }, addMode: function (main, extended) @@ -186,7 +186,7 @@ const vimperator = (function () //{{{ if (main) mode |= main; if (extended) - extended_mode |= extended; + extendedMode |= extended; showMode(); }, @@ -197,7 +197,7 @@ const vimperator = (function () //{{{ if (main) mode = (mode | main) ^ main; if (extended) - extended_mode = (extended_mode | extended) ^ extended; + extendedMode = (extendedMode | extended) ^ extended; showMode(); }, @@ -217,13 +217,13 @@ const vimperator = (function () //{{{ vbell.style.left = box.x + "px"; vbell.style.top = box.y + "px"; - vbell.hidden = false + vbell.hidden = false; setTimeout(function () { vbell.hidden = true; }, 50); // may as well be 0 ;-) } else { - sound_service.beep(); + soundService.beep(); } }, @@ -409,7 +409,7 @@ const vimperator = (function () //{{{ if (typeof msg == "object") msg = this.objectToString(msg, false); - console_service.logStringMessage("vimperator: " + msg); + consoleService.logStringMessage("vimperator: " + msg); }, // open one or more URLs @@ -482,9 +482,9 @@ const vimperator = (function () //{{{ }, // quit vimperator, no matter how many tabs/windows are open - quit: function (save_session) + quit: function (saveSession) { - if (save_session) + if (saveSession) vimperator.options.setFirefoxPref("browser.startup.page", 3); // start with saved session else vimperator.options.setFirefoxPref("browser.startup.page", 1); // start with default homepage session @@ -532,7 +532,7 @@ const vimperator = (function () //{{{ if (!args) args = []; - if (typeof(blocking) != "boolean") + if (typeof blocking != "boolean") blocking = false; try @@ -541,7 +541,7 @@ const vimperator = (function () //{{{ } catch (e) { - var dirs = environment_service.get("PATH").split(WINDOWS ? ";" : ":"); + var dirs = environmentService.get("PATH").split(WINDOWS ? ";" : ":"); for (var i = 0; i < dirs.length; i++) { var path = dirs[i] + (WINDOWS ? "\\" : "/") + program; @@ -604,8 +604,8 @@ const vimperator = (function () //{{{ filein.remove(false); // if there is only one \n at the end, chop it off - if (output && output.indexOf("\n") == output.length-1) - output = output.substr(0, output.length-1); + if (output && output.indexOf("\n") == output.length - 1) + output = output.substr(0, output.length - 1); return output; }, @@ -628,16 +628,16 @@ const vimperator = (function () //{{{ else { var heredoc = ""; - var heredoc_end = null; // the string which ends the heredoc + var heredocEnd = null; // the string which ends the heredoc str.split("\n").forEach(function (line) { - if (heredoc_end) // we already are in a heredoc + if (heredocEnd) // we already are in a heredoc { - if (heredoc_end.test(line)) + if (heredocEnd.test(line)) { eval(heredoc); heredoc = ""; - heredoc_end = null; + heredocEnd = null; } else { @@ -654,7 +654,7 @@ const vimperator = (function () //{{{ var matches = args.match(/(.*)<<\s*([^\s]+)$/); if (matches) { - heredoc_end = new RegExp("^" + matches[2] + "$", "m"); + heredocEnd = new RegExp("^" + matches[2] + "$", "m"); if (matches[1]) heredoc = matches[1] + "\n"; } @@ -688,51 +688,51 @@ const vimperator = (function () //{{{ // these objects are created here only after the chrome is ready vimperator.log("Loading module options...", 3); - vimperator.options = new vimperator.Options(); + vimperator.options = vimperator.Options(); vimperator.log("Loading module events...", 3); - vimperator.events = new vimperator.Events(); + vimperator.events = vimperator.Events(); vimperator.log("Loading module commands...", 3); - vimperator.commands = new vimperator.Commands(); + vimperator.commands = vimperator.Commands(); vimperator.log("Loading module bookmarks...", 3); - vimperator.bookmarks = new vimperator.Bookmarks(); + vimperator.bookmarks = vimperator.Bookmarks(); vimperator.log("Loading module history...", 3); - vimperator.history = new vimperator.History(); + vimperator.history = vimperator.History(); vimperator.log("Loading module commandline...", 3); - vimperator.commandline = new vimperator.CommandLine(); + vimperator.commandline = vimperator.CommandLine(); vimperator.log("Loading module search...", 3); - vimperator.search = new vimperator.Search(); + vimperator.search = vimperator.Search(); vimperator.log("Loading module preview window...", 3); - vimperator.previewwindow = new vimperator.InformationList("vimperator-previewwindow", { incremental_fill: false, max_items: 10 }); + vimperator.previewwindow = vimperator.InformationList("vimperator-previewwindow", { incrementalFill: false, maxItems: 10 }); vimperator.log("Loading module buffer window...", 3); - vimperator.bufferwindow = new vimperator.InformationList("vimperator-bufferwindow", { incremental_fill: false, max_items: 10 }); + vimperator.bufferwindow = vimperator.InformationList("vimperator-bufferwindow", { incrementalFill: false, maxItems: 10 }); vimperator.log("Loading module mappings...", 3); - vimperator.mappings = new vimperator.Mappings(); + vimperator.mappings = vimperator.Mappings(); vimperator.log("Loading module statusline...", 3); - vimperator.statusline = new vimperator.StatusLine(); + vimperator.statusline = vimperator.StatusLine(); vimperator.log("Loading module buffer...", 3); - vimperator.buffer = new vimperator.Buffer(); + vimperator.buffer = vimperator.Buffer(); vimperator.log("Loading module tabs...", 3); - vimperator.tabs = new vimperator.Tabs(); + vimperator.tabs = vimperator.Tabs(); vimperator.log("Loading module marks...", 3); - vimperator.marks = new vimperator.Marks(); + vimperator.marks = vimperator.Marks(); vimperator.log("Loading module quickmarks...", 3); - vimperator.quickmarks = new vimperator.QuickMarks(); + vimperator.quickmarks = vimperator.QuickMarks(); vimperator.log("Loading module hints...", 3); - vimperator.hints = new vimperator.Hints(); + vimperator.hints = vimperator.Hints(); vimperator.log("Loading module io...", 3); - vimperator.io = new vimperator.IO(); + vimperator.io = vimperator.IO(); vimperator.log("Loading module completion...", 3); - vimperator.completion = new vimperator.Completion(); + vimperator.completion = vimperator.Completion(); vimperator.log("All modules loaded", 3); - vimperator.echo = function (str) { vimperator.commandline.echo(str); } - vimperator.echoerr = function (str) { vimperator.commandline.echo(str, vimperator.commandline.HL_ERRORMSG); } + vimperator.echo = function (str, flags) { vimperator.commandline.echo(str, vimperator.commandline.HL_NORMAL, flags); }; + vimperator.echoerr = function (str, flags) { vimperator.commandline.echo(str, vimperator.commandline.HL_ERRORMSG, flags); }; vimperator.globalVariables = {}; // TODO: move elsewhere - vimperator.registerCallback("submit", vimperator.modes.EX, function (command) { vimperator.execute(command); } ); - vimperator.registerCallback("complete", vimperator.modes.EX, function (str) { return vimperator.completion.exTabCompletion(str); } ); + vimperator.registerCallback("submit", vimperator.modes.EX, function (command) { vimperator.execute(command); }); + vimperator.registerCallback("complete", vimperator.modes.EX, function (str) { return vimperator.completion.exTabCompletion(str); }); // first time intro message if (vimperator.options.getPref("firsttime", true)) @@ -749,20 +749,20 @@ const vimperator = (function () //{{{ // make sourcing asynchronous, otherwise commands that open new tabs won't work setTimeout(function () { - var rc_file = vimperator.io.getRCFile(); + var rcFile = vimperator.io.getRCFile(); - if (rc_file) - vimperator.source(rc_file.path, true); + if (rcFile) + vimperator.source(rcFile.path, true); else vimperator.log("No user RC file found", 3); // also source plugins in ~/.vimperator/plugin/ try { - var plugin_dir = vimperator.io.getPluginDir(); - if (plugin_dir) + var pluginDir = vimperator.io.getPluginDir(); + if (pluginDir) { - var files = vimperator.io.readDirectory(plugin_dir.path); + var files = vimperator.io.readDirectory(pluginDir.path); vimperator.log("Sourcing plugin directory...", 3); files.forEach(function (file) { if (!file.isDirectory() && /\.js$/.test(file.path)) @@ -809,21 +809,22 @@ const vimperator = (function () //{{{ var mainThread = threadManager.mainThread; var then = new Date().getTime(), now = then; - for (; now - then < ms; now = new Date().getTime()) { + for (; now - then < ms; now = new Date().getTime()) mainThread.processNextEvent(true); - } }, get windows() { - var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator); + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); var wa = []; var enumerator = wm.getEnumerator("navigator:browser"); while (enumerator.hasMoreElements()) wa.push(enumerator.getNext()); return wa; } - } //}}} + + }; //}}} })(); //}}} // called when the chrome is fully loaded and before the main window is shown