summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Rosenthal <jack@rosenth.al>2019-07-08 19:14:14 -0600
committerJack Rosenthal <jack@rosenth.al>2019-07-08 19:14:14 -0600
commit3905c10ad8e0da2b73760c97644df47604d7366e (patch)
tree941cc59511f86f2e25ae89a7996e0139cbe0e552
parentdfcffbc39f0ca29a9fb42711fa0a7086d4bba7c9 (diff)
downloadpentadactyl-3905c10ad8e0da2b73760c97644df47604d7366e.tar.gz
Delete melodactyl and teledactyl
Nobody is around to support this code anymore. Delete it so we can focus our efforts on just Pentadactyl. BUG=#2
-rw-r--r--melodactyl/AUTHORS6
-rw-r--r--melodactyl/Makefile11
-rwxr-xr-xmelodactyl/NEWS18
-rw-r--r--melodactyl/TODO25
l---------melodactyl/chrome.manifest1
l---------melodactyl/components/commandline-handler.js1
-rw-r--r--melodactyl/content/config.js334
-rw-r--r--melodactyl/content/library.js64
-rw-r--r--melodactyl/content/logo.pngbin1082 -> 0 bytes
-rw-r--r--melodactyl/content/player.js852
-rw-r--r--melodactyl/defaults/preferences/dactyl.js6
-rw-r--r--melodactyl/install.rdf25
-rw-r--r--melodactyl/locale/en-US/all.xml14
-rw-r--r--melodactyl/locale/en-US/autocommands.xml51
-rw-r--r--melodactyl/locale/en-US/browsing.xml17
-rw-r--r--melodactyl/locale/en-US/gui.xml31
-rw-r--r--melodactyl/locale/en-US/intro.xml144
-rw-r--r--melodactyl/locale/en-US/map.xml51
-rw-r--r--melodactyl/locale/en-US/messages.properties10
-rw-r--r--melodactyl/locale/en-US/player.xml328
-rw-r--r--melodactyl/locale/en-US/tabs.xml16
-rw-r--r--melodactyl/skin/icon.pngbin465 -> 0 bytes
-rw-r--r--teledactyl/AUTHORS11
-rw-r--r--teledactyl/Makefile12
-rw-r--r--teledactyl/NEWS0
-rw-r--r--teledactyl/TODO17
l---------teledactyl/bootstrap.js1
l---------teledactyl/chrome.manifest1
l---------teledactyl/components/commandline-handler.js1
-rw-r--r--teledactyl/config.json71
-rw-r--r--teledactyl/content/addressbook.js155
-rw-r--r--teledactyl/content/compose/compose.js83
-rw-r--r--teledactyl/content/compose/compose.xul19
-rw-r--r--teledactyl/content/config.js174
-rw-r--r--teledactyl/content/logo.pngbin3731 -> 0 bytes
-rw-r--r--teledactyl/content/mail.js946
-rw-r--r--teledactyl/defaults/preferences/dactyl.js6
-rw-r--r--teledactyl/install.rdf24
-rw-r--r--teledactyl/locale/en-US/Makefile3
-rw-r--r--teledactyl/locale/en-US/all.xml11
-rw-r--r--teledactyl/locale/en-US/autocommands.xml37
-rw-r--r--teledactyl/locale/en-US/intro.xml138
-rw-r--r--teledactyl/locale/en-US/map.xml47
-rw-r--r--teledactyl/locale/en-US/messages.properties14
-rw-r--r--teledactyl/skin/icon.pngbin408 -> 0 bytes
45 files changed, 0 insertions, 3776 deletions
diff --git a/melodactyl/AUTHORS b/melodactyl/AUTHORS
deleted file mode 100644
index 4c5be983..00000000
--- a/melodactyl/AUTHORS
+++ /dev/null
@@ -1,6 +0,0 @@
-Main developer/Project founder:
- * Prathyush Thota <prathyushthota@gmail.com>
-
-Developers:
- * Martin Stubenschrott (stubenschrott@vimperator.org)
- * Doug Kearns (dougkearns@gmail.com)
diff --git a/melodactyl/Makefile b/melodactyl/Makefile
deleted file mode 100644
index ed90a968..00000000
--- a/melodactyl/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#### configuration
-
-NAME = melodactyl
-
-SONGBIRD ?= songbird
-HOSTAPP ?= $(SONGBIRD)
-PROFILEPATHS ?= "$$HOME/.songbird2" \
- "$$HOME/Library/Songbird2" \
- "$$APPDATA/Songbird2"
-
-include ../common/Makefile
diff --git a/melodactyl/NEWS b/melodactyl/NEWS
deleted file mode 100755
index 2bbbde98..00000000
--- a/melodactyl/NEWS
+++ /dev/null
@@ -1,18 +0,0 @@
-0.1a1pre:
- * :playerprev and :playernext and equivalent mappings now accept a count.
- * :displaypane arguments changed to "leftservice", "bottomservice",
- "bottomcontent" or "rightsidebar"
- * asciidoc is no longer required to build Melodactyl
- * The help system is newly modularized
- * add :silent
- * add $MY_MELODACTYLRC
- * add ' and " local marks
- * add w and W Normal mode mappings for symmetry with o/O and t/T
- * add :messclear
- * add 'maxitems'
- * :dialog {subscribe|newsmartplaylist}
- * add :displaypane and :dpclose
- * rename :filter to :queue and :Filter to :filter
- * add 'repeat' and 'shuffle'
- * add 'jsdebugger' option - switch on/off javascript debugger service
- * add "addons", "downloads", "extoptions" and "help" to the 'activate' option.
diff --git a/melodactyl/TODO b/melodactyl/TODO
deleted file mode 100644
index af6f4ff3..00000000
--- a/melodactyl/TODO
+++ /dev/null
@@ -1,25 +0,0 @@
-Priority list:
-1-9 as in Vim (9 = required for next release, 5 = would be nice, 1 = probably not)
-
-BUGS:
-- broken commands:
- - :tabduplicate
- - :open songbird-internal-search searchString (broken because SB intercepts queries to this engine)
- - <C-^> only works between browser tabs not the media tab
- - numbered tabs
-
-FEATURES:
-9 Clean up NEWS
-9 Bookmarks are now only supported in SB via an addon.
-9 '?' - Reusing '/'.
-8 Merge with SongBird's sanitizer implementation.
-8 Playlist/SmartPlaylist operations & meta-data operations.
-8 Sort-View commands.
-7 Queue view.
-7 j/k - for browsing through the visible view.
-7 extended hint mode for opening links in FF.
-6 :tqueue, :lqueue etc.
-5 make Player mode commands work in the Mini-Player.
-5 Check for default extensions and add commands for them. Ex. Last.fm, Seeqpod e.t.c
- Wouldn't these be provided as Melodactyl plugins like Pentadactyl does? --djk
-5 tagging tracks for manipulation by commands
diff --git a/melodactyl/chrome.manifest b/melodactyl/chrome.manifest
deleted file mode 120000
index 40321439..00000000
--- a/melodactyl/chrome.manifest
+++ /dev/null
@@ -1 +0,0 @@
-../common/chrome.manifest \ No newline at end of file
diff --git a/melodactyl/components/commandline-handler.js b/melodactyl/components/commandline-handler.js
deleted file mode 120000
index aa8427b9..00000000
--- a/melodactyl/components/commandline-handler.js
+++ /dev/null
@@ -1 +0,0 @@
-../../common/components/commandline-handler.js \ No newline at end of file
diff --git a/melodactyl/content/config.js b/melodactyl/content/config.js
deleted file mode 100644
index 79768a1c..00000000
--- a/melodactyl/content/config.js
+++ /dev/null
@@ -1,334 +0,0 @@
-// Copyright (c) 2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
-// Copyright (c) 2009 by Prathyush Thota <prathyushthota@gmail.com>
-// Copyright (c) 2009-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2009-2011 by Kris Maglione <maglione.k@gmail.com>
-//
-// This work is licensed for reuse under an MIT license. Details are
-// given in the LICENSE.txt file included with this file.
-"use strict";
-
-Components.utils.import("resource://gre/modules/utils.js"); // XXX: PlacesUtils
-
-const Config = Module("config", ConfigBase, {
- name: "melodactyl",
- appName: "Melodactyl",
- idName: "MELODACTYL",
- host: "Songbird",
- hostbin: "songbird",
-
- commandContainer: "mainplayer",
-
- Local: function Local(dactyl, modules, window) let ({ config } = modules, { document } = window) {
- init: function init() {
- init.supercall(this);
-
- // TODO: mention this to SB devs, they seem keen to provide these
- // functions to make porting from FF as simple as possible.
- window.toJavaScriptConsole = () => {
- toOpenWindowByType("global:console", "chrome://global/content/console.xul");
- };
- },
-
- // FIXME: unless I'm seeing double in in the wee small hours gBrowser is
- // first set from getBrowser which they've deprecated in FF.
- get browser() { return window.getBrowser(); },
- get tabbrowser() { return window.getBrowser(); },
-
- dialogs: {
- about: ["About Songbird",
- () => { window.openDialog("chrome://songbird/content/xul/about.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
- addons: ["Manage Add-ons",
- () => { window.SBOpenPreferences("paneAddons"); }],
- checkupdates: ["Check for updates",
- () => { window.checkForUpdates(); }],
- cookies: ["List your cookies",
- () => { window.toOpenWindowByType("Browser:Cookies", "chrome://browser/content/preferences/cookies.xul", "chrome,dialog=no,resizable"); }],
- console: ["JavaScript console",
- () => { window.toJavaScriptConsole(); }],
- dominspector: ["DOM Inspector",
- () => { window.inspectDOMDocument(window.content.document); },
- () => "inspectDOMDocument" in window],
- downloads: ["Manage Downloads",
- () => { window.toOpenWindowByType("Download:Manager", "chrome://mozapps/content/downloads/downloads.xul", "chrome,dialog=no,resizable"); }],
- newsmartplaylist: ["Open the file selector dialog",
- () => { window.SBNewSmartPlaylist(); }],
- openfile: ["Open the file selector dialog",
- () => { window.SBFileOpen(); }],
- pagesource: ["View page source",
- () => { window.BrowserViewSourceOfDocument(window.content.document); }],
- preferences: ["Show Songbird preferences dialog",
- () => { window.openPreferences(); }],
- printsetup: ["Setup the page size and orientation before printing",
- () => { window.PrintUtils.showPageSetup(); }],
- print: ["Show print dialog",
- () => { window.PrintUtils.print(); }],
- saveframe: ["Save frame to disk",
- () => { window.saveFrameDocument(); }],
- savepage: ["Save page to disk",
- () => { window.saveDocument(window.content.document); }],
- searchengines: ["Manage installed search engines",
- () => { window.openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
- selectionsource: ["View selection source",
- () => { modules.buffer.viewSelectionSource(); }],
- subscribe: ["Add a new subscription",
- () => { window.SBSubscribe(); }]
- },
-
- // TODO: clean this up
- focusChange: function (win) {
- const { modes } = modules;
-
- // Switch to -- PLAYER -- mode for Songbird Media Player.
- if (this.isPlayerWindow)
- modes.set(modes.PLAYER);
- else
- if (modes.main == modes.PLAYER)
- modes.pop();
- },
-
- get isPlayerWindow() {
- let browser = window.SBGetBrowser();
- return browser.mCurrentTab == browser.mediaTab;
- },
-
- /**
- * Shows or hides the main service pane.
- *
- * @param {boolean} value Show the service pane if true, hide it if false.
- */
- showServicePane: function (value) {
- const key = "splitter.servicepane_splitter.was_collapsed";
- window.gServicePane.open = value;
- window.SBDataSetBoolValue(key, window.gServicePane.open);
- },
-
- /**
- * Opens the display panel with the specified *id*.
- *
- * @param {string} id The ID of the display pane.
- */
- openDisplayPane: function (id) {
- if (id == "servicepane")
- this.showServicePane(true);
- else {
- let pane = document.getElementById(id);
- let manager = services.displayPaneManager;
- let paneinfo = manager.getPaneInfo(pane._lastURL.stringValue);
-
- if (!paneinfo)
- paneinfo = manager.defaultPaneInfo;
-
- pane.loadContent(paneinfo);
- }
- },
-
- /**
- * Closes the display panel with the specified *id*
- *
- * @param {string} id The ID of the display pane.
- */
- closeDisplayPane: function (id) {
- if (id == "servicepane")
- this.showServicePane(false);
- else
- document.getElementById(id).hide();
- }
- },
-
- /*** optional options, there are checked for existence and a fallback provided ***/
- features: Set(["bookmarks", "hints", "marks", "history", "quickmarks", "session", "tabs", "player"]),
-
- defaults: {
- guioptions: "bCmprs",
- showtabline: 2,
- get titlestring() { return config.name; }
- },
-
- guioptions: {
- m: ["Menubar", ["main-menubar"]],
- T: ["Toolbar", ["nav-bar"]],
- p: ["Player controls", ["player_wrapper"]]
- },
-
- overlayChrome: ["chrome://purplerain/content/xul/mainplayer.xul"],
-
- styleableChrome: ["chrome://purplerain/content/xul/mainplayer.xul"],
-
- autocommands: {
- BookmarkAdd: "Triggered after a page is bookmarked",
- ColorScheme: "Triggered after a color scheme has been loaded",
- DOMLoad: "Triggered when a page's DOM content has fully loaded",
- DownloadPost: "Triggered when a download has completed",
- Fullscreen: "Triggered when the browser's fullscreen state changes",
- LocationChange: "Triggered when changing tabs or when navigation to a new location",
- PageLoadPre: "Triggered after a page load is initiated",
- PageLoad: "Triggered when a page gets (re)loaded/opened",
- ShellCmdPost: "Triggered after executing a shell command with :!cmd",
- TrackChangePre: "Triggered before a playing track is changed",
- TrackChange: "Triggered after a playing track has changed",
- ViewChangePre: "Triggered before a sequencer view is changed",
- ViewChange: "Triggered after a sequencer view is changed",
- StreamStart: "Triggered after a stream has started",
- StreamPause: "Triggered after a stream has paused",
- StreamEnd: "Triggered after a stream has ended",
- StreamStop: "Triggered after a stream has stopped",
- Enter: "Triggered after Songbird starts",
- LeavePre: "Triggered before exiting Songbird, just before destroying each module",
- Leave: "Triggered before exiting Songbird"
- },
-
- completers: Class.memoize(function () {
- return update({
- displaypane: "displayPane",
- playlist: "playlist",
- mediaview: "mediaView",
- mediasort: "mediaListSort",
- song: "song"
- }, this.__proto__.completers);
- }),
-
- removeTab: function (tab) {
- if (config.tabbrowser.mTabs.length > 1)
- config.tabbrowser.removeTab(tab);
- else {
- if (buffer.URL != "about:blank" || window.getWebNavigation().sessionHistory.count > 0) {
- dactyl.open("about:blank", dactyl.NEW_BACKGROUND_TAB);
- config.tabbrowser.removeTab(tab);
- }
- else
- dactyl.beep();
- }
- },
-
- scripts: [
- "browser",
- "bookmarks",
- "history",
- "quickmarks",
- "tabs",
- "player",
- "library"
- ],
-
- sidebars: {
- viewAddons: ["Add-ons", "A", "chrome://mozapps/content/extensions/extensions.xul"],
- viewConsole: ["Console", "C", "chrome://global/content/console.xul"],
- viewDownloads: ["Downloads", "D", "chrome://mozapps/content/downloads/downloads.xul"],
- viewPreferences: ["Preferences", "P", "about:config"]
- },
-
- // FIXME: tab arg and media tab exception?
- stop: function (tab) {
- window.SBGetBrowser().mCurrentBrowser.stop();
- }
-}, {
- /**
- * @property {object} A map of display pane command argument strings to
- * panel element IDs.
- */
- displayPanes: {
- "leftservice" : "servicepane",
- "bottomcontent": "displaypane_contentpane_bottom",
- "bottomservice": "displaypane_servicepane_bottom",
- "rightsidebar" : "displaypane_right_sidebar"
- }
-}, {
- commands: function initCommands(dactyl, modules, window) {
- const { commands, completion, options } = modules;
-
- commands.add(["dpcl[ose]"],
- "Close a display pane",
- function (args) {
- let arg = args.literalArg;
- dactyl.assert(arg in Config.displayPanes, _("error.invalidArgument", arg));
- config.closeDisplayPane(Config.displayPanes[arg]);
- }, {
- argCount: "1",
- completer: function (context) {
- completion.displayPane(context);
- },
- literal: 0
- });
-
- // TODO: this should accept a second arg to specify content
- commands.add(["displayp[ane]", "dp[ane]", "dpope[n]"],
- "Open a display pane",
- function (args) {
- let arg = args.literalArg;
- dactyl.assert(arg in Config.displayPanes, _("error.invalidArgument", arg));
- // TODO: focus when we have better key handling of these extended modes
- config.openDisplayPane(Config.displayPanes[arg]);
- }, {
- argCount: "1",
- completer: function (context) {
- completion.displayPane(context);
- },
- literal: 0
- });
-
- commands.add(["pref[erences]", "prefs"],
- "Show " + config.host + " preferences",
- function (args) {
- if (args.bang) { // open Songbird settings GUI dialog
- dactyl.open("about:config",
- (options["newtab"] && options.get("newtab").has("all", "prefs"))
- ? dactyl.NEW_TAB : dactyl.CURRENT_TAB);
- }
- else
- window.openPreferences();
- },
- {
- argCount: "0",
- bang: true
- });
- },
- completion: function initCompletion(dactyl, modules, window) {
- const completion = require("completion");
-
- completion.displayPane = context => {
- context.title = ["Display Pane"];
- context.completions = Config.displayPanes; // FIXME: useful description etc
- };
- },
- modes: function initModes(dactyl, modules, window) {
- const { modes } = modules;
-
- this.ignoreKeys = {
- "<Return>": modes.NORMAL | modes.INSERT,
- "<Space>": modes.NORMAL | modes.INSERT,
- "<Up>": modes.NORMAL | modes.INSERT,
- "<Down>": modes.NORMAL | modes.INSERT
- };
-
- modes.addMode("PLAYER", {
- char: "p"
- });
- },
- options: function initOptions(dactyl, modules, window) {
- const { options } = modules;
-
- // TODO: SB doesn't explicitly support an offline mode. Should we? --djk
- options.add(["online"],
- "Set the 'work offline' option",
- "boolean", true,
- {
- setter: function (value) {
- const ioService = services.io;
- ioService.offline = !value;
- prefs.set("browser.offline", ioService.offline);
- return value;
- },
- getter: function () { return !services.io.offline; }
- });
- },
- services: function initServices(dactyl, modules, window) {
- services.add("displayPaneManager", "@songbirdnest.com/Songbird/DisplayPane/Manager;1", Ci.sbIDisplayPaneManager);
- services.add("mediaPageManager", "@songbirdnest.com/Songbird/MediaPageManager;1", Ci.sbIMediaPageManager);
- services.add("propertyManager", "@songbirdnest.com/Songbird/Properties/PropertyManager;1", Ci.sbIPropertyManager);
-
- services.addClass("mutablePropertyArray", "@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1",
- Ci.sbIMutablePropertyArray);
- }
-});
-
-// vim: set fdm=marker sw=4 sts=4 ts=8 et:
diff --git a/melodactyl/content/library.js b/melodactyl/content/library.js
deleted file mode 100644
index 65bfb768..00000000
--- a/melodactyl/content/library.js
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2009 by Prathyush Thota <prathyushthota@gmail.com>
-// Copyright (c) 2009 by Doug Kearns <dougkearns@gmail.com>
-//
-// This work is licensed for reuse under an MIT license. Details are
-// given in the LICENSE.txt file included with this file.
-"use strict";
-
-// TODO: flesh this out
-const Library = Module("library", {
- init: function () {
- this.MAIN_LIBRARY = LibraryUtils.mainLibrary;
- },
-
- /**
- * Converts an XPCOM enumerator to a JavaScript array.
- *
- * @param {nsISimpleEnumerator|nsIStringEnumerator|nsIArray} enum The enumerator to convert.
- * @returns {Array}
- */
- _toJSArray: function _toJSArray(enum) ArrayConverter.JSArray(enum),
-
- /**
- * Returns an array of all the artist names in the main library.
- *
- * @returns {[string]}
- */
- getArtists: function getArtists() this._toJSArray(this.MAIN_LIBRARY.getDistinctValuesForProperty(SBProperties.artistName)),
-
- // FIXME: Prathyush do we really want to remove duplicates? If so, why not tracks too? --djk
- /**
- * Returns an array of all the album names for *artist* in the main
- * library.
- *
- * @param {string} artist The artist's name.
- * @returns {[string]}
- */
- getAlbums: function getAlbums(artist) {
- let albums = this._toJSArray(this.MAIN_LIBRARY.getItemsByProperty(SBProperties.artistName, artist))
- .map(track => track.getProperty(SBProperties.albumName));
- return array.uniq(albums);
- },
-
- /**
- * Returns an array of all the track names for *artist* and *album* in the
- * main library.
- *
- * @param {string} artist The artist's name.
- * @param {string} album The album's name.
- * @returns {[string]}
- */
- getTracks: function getTracks(artist, album) {
- let properties = services.MutablePropertyArray();
-
- properties.appendProperty(SBProperties.artistName, artist);
- properties.appendProperty(SBProperties.albumName, album);
-
- return this._toJSArray(this.MAIN_LIBRARY.getItemsByProperties(properties))
- .map(track => track.getProperty(SBProperties.trackName));
- }
-}, {
-}, {
-});
-
-// vim: set fdm=marker sw=4 sts=4 ts=8 et:
diff --git a/melodactyl/content/logo.png b/melodactyl/content/logo.png
deleted file mode 100644
index e907ad05..00000000
--- a/melodactyl/content/logo.png
+++ /dev/null
Binary files differ
diff --git a/melodactyl/content/player.js b/melodactyl/content/player.js
deleted file mode 100644
index f0f8d44a..00000000
--- a/melodactyl/content/player.js
+++ /dev/null
@@ -1,852 +0,0 @@
-// Copyright (c) 2009 by Prathyush Thota <prathyushthota@gmail.com>
-// Copyright (c) 2009 by Doug Kearns <dougkearns@gmail.com>
-//
-// This work is licensed for reuse under an MIT license. Details are
-// given in the LICENSE.txt file included with this file.
-"use strict";
-
-const Player = Module("player", {
- init: function init() {
- this._lastSearchString = "";
- this._lastSearchIndex = 0;
- this._lastSearchView = this._currentView; //XXX
-
- // Get the focus to the visible playlist first
- //window._SBShowMainLibrary();
-
- gMM.addListener(this._mediaCoreListener);
- },
-
- destroy: function destroy() {
- gMM.removeListener(this._mediaCoreListener);
- },
-
- /**
- * Moves the track position *interval* milliseconds forwards or backwards.
- *
- * @param {number} interval The time interval (ms) to move the track
- * position.
- * @param {boolean} direction The direction in which to move the track
- * position, forward if true otherwise backwards.
- * @private
- */
- _seek: function _seek(interval, direction) {
- let position = gMM.playbackControl ? gMM.playbackControl.position : 0;
- player.seekTo(position + (direction ? interval : -interval));
- },
-
- /**
- * Listens for media core events and in response dispatches the appropriate
- * autocommand events.
- * @private
- */
- _mediaCoreListener: {
- onMediacoreEvent: function (event) {
- switch (event.type) {
- case Ci.sbIMediacoreEvent.BEFORE_TRACK_CHANGE:
- dactyl.log(_("player.preTrackChange", event.data));
- autocommands.trigger("TrackChangePre", { track: event.data });
- break;
- case Ci.sbIMediacoreEvent.TRACK_CHANGE:
- dactyl.log(_("player.trackChanged", event.data));
- autocommands.trigger("TrackChange", { track: event.data });
- break;
- case Ci.sbIMediacoreEvent.BEFORE_VIEW_CHANGE:
- dactyl.log(_("player.preViewChange", event.data));
- autocommands.trigger("ViewChangePre", { view: event.data });
- break;
- case Ci.sbIMediacoreEvent.VIEW_CHANGE:
- dactyl.log(_("player.viewChange", event.data));
- autocommands.trigger("ViewChange", { view: event.data });
- break;
- case Ci.sbIMediacoreEvent.STREAM_START:
- dactyl.log(_("player.trackStart", gMM.sequencer.currentItem));
- autocommands.trigger("StreamStart", { track: gMM.sequencer.currentItem });
- break;
- case Ci.sbIMediacoreEvent.STREAM_PAUSE:
- dactyl.log(_("player.trackPause", gMM.sequencer.currentItem));
- autocommands.trigger("StreamPause", { track: gMM.sequencer.currentItem });
- break;
- case Ci.sbIMediacoreEvent.STREAM_END:
- dactyl.log(_("player.trackEnd", gMM.sequencer.currentItem));
- autocommands.trigger("StreamEnd", { track: gMM.sequencer.currentItem });
- break;
- case Ci.sbIMediacoreEvent.STREAM_STOP:
- dactyl.log(_("player.trackStop", gMM.sequencer.currentItem));
- autocommands.trigger("StreamStop", { track: gMM.sequencer.currentItem });
- break;
- }
- }
- },
-
- /** @property {sbIMediaListView} The current media list view. @private */
- get _currentView() { return SBGetBrowser().currentMediaListView; },
-
- /**
- * @property {number} The player volume in the range 0.0-1.0.
- */
- get volume() { return gMM.volumeControl.volume; },
- set volume(value) {
- gMM.volumeControl.volume = value;
- },
-
- /**
- * Focuses the specified media item in the current media list view.
- *
- * @param {sbIMediaItem} mediaItem The media item to focus.
- */
- focusTrack: function focusTrack(mediaItem) {
- SBGetBrowser().mediaTab.mediaPage.highlightItem(this._currentView.getIndexForItem(mediaItem));
- },
-
- /**
- * Plays the currently selected media item. If no item is selected the
- * first item in the current media view is played.
- */
- play: function play() {
- // Check if there is any selection in place, else play first item of the visible view.
- // TODO: this approach, or similar, should be generalised for all commands, PT? --djk
- if (this._currentView.selection.count != 0)
- gMM.sequencer.playView(this._currentView,
- this._currentView.getIndexForItem(this._currentView.selection.currentMediaItem));
- else
- gMM.sequencer.playView(SBGetBrowser().currentMediaListView, 0);
-
- this.focusTrack(gMM.sequencer.currentItem);
- },
-
- /**
- * Stops playback of the currently playing media item.
- */
- stop: function stop() {
- gMM.sequencer.stop();
- },
-
- /**
- * Plays the *count*th next media item in the current media view.
- *
- * @param {number} count
- */
- next: function next(count) {
- for (let i = 0; i < count; i++)
- gSongbirdWindowController.doCommand("cmd_control_next");
- gSongbirdWindowController.doCommand("cmd_find_current_track");
- },
-
- /**
- * Plays the *count*th previous media item in the current media view.
- *
- * @param {number} count
- */
- previous: function previous(count) {
- for (let i = 0; i < count; i++)
- gSongbirdWindowController.doCommand("cmd_control_previous");
- gSongbirdWindowController.doCommand("cmd_find_current_track");
- },
-
- /**
- * Toggles the play/pause status of the current media item.
- */
- togglePlayPause: function togglePlayPause() {
- ["cmd_control_playpause", "cmd_find_current_track"].forEach(gSongbirdWindowController.doCommand);
- },
-
- /**
- * Toggles the shuffle status of the sequencer.
- */
- toggleShuffle: function toggleShuffle() {
- if (gMM.sequencer.mode != gMM.sequencer.MODE_SHUFFLE)
- gMM.sequencer.mode = gMM.sequencer.MODE_SHUFFLE;
- else
- gMM.sequencer.mode = gMM.sequencer.MODE_FORWARD;
- },
-
- // FIXME: not really toggling (depending on your definition) - good enough for now.
- /**
- * Toggles between the sequencer's three repeat modes: Repeat-One,
- * Repeat-All and Repeat-None.
- */
- toggleRepeat: function toggleRepeat() {
- switch (gMM.sequencer.repeatMode) {
- case gMM.sequencer.MODE_REPEAT_NONE:
- gMM.sequencer.repeatMode = gMM.sequencer.MODE_REPEAT_ONE;
- break;
- case gMM.sequencer.MODE_REPEAT_ONE:
- gMM.sequencer.repeatMode = gMM.sequencer.MODE_REPEAT_ALL;
- break;
- case gMM.sequencer.MODE_REPEAT_ALL:
- gMM.sequencer.repeatMode = gMM.sequencer.MODE_REPEAT_NONE;
- break;
- default:
- gMM.sequencer.repeatMode = gMM.sequencer.MODE_REPEAT_NONE;
- break;
- }
- },
-
- /**
- * Seeks forward *interval* milliseconds in the currently playing track.
- *
- * @param {number} interval The time interval (ms) to advance the
- * current track.
- */
- seekForward: function seekForward(interval) {
- this._seek(interval, true);
- },
-
- /**
- * Seeks backwards *interval* milliseconds in the currently playing track.
- *
- * @param {number} interval The time interval (ms) to rewind the
- * current track.
- */
- seekBackward: function seekBackward(interval) {
- this._seek(interval, false);
- },
-
- /**
- * Seeks to a specific position in the currently playing track.
- *
- * @param {number} The new position (ms) in the track.
- */
- seekTo: function seekTo(position) {
- // FIXME: if not playing
- if (!gMM.playbackControl)
- this.play();
-
- let min = 0;
- let max = gMM.playbackControl.duration - 5000; // TODO: 5s buffer like cmus desirable?
-
- gMM.playbackControl.position = Math.constrain(position, min, max);
- },
-
- /**
- * Increases the volume by 5% of the maximum volume.
- */
- increaseVolume: function increaseVolume() {
- this.volume = Math.constrain(this.volume + 0.05, 0, 1);
- },
-
- /**
- * Decreases the volume by 5% of the maximum volume.
- */
- decreaseVolume: function decreaseVolume() {
- this.volume = Math.constrain(this.volume - 0.05, 0, 1);
- },
-
- // TODO: Document what this buys us over and above cmd_find_current_track
- /**
- * Focuses the currently playing track.
- */
- focusPlayingTrack: function focusPlayingTrack() {
- this.focusTrack(gMM.sequencer.currentItem);
- },
-
- /**
- * Searches the current media view for *str*
- *
- * @param {string} str The search string.
- */
- searchView: function searchView(str) {
- let search = _getSearchString(this._currentView);
- let searchString = "";
-
- if (search != "") // XXX
- searchString = str + " " + search;
- else
- searchString = str;
-
- this._lastSearchString = searchString;
-
- let searchView = LibraryUtils.createStandardMediaListView(this._currentView.mediaList, searchString);
-
- if (searchView.length) {
- this._lastSearchView = searchView;
- this._lastSearchIndex = 0;
- this.focusTrack(searchView.getItemByIndex(this._lastSearchIndex));
- }
- else
- dactyl.echoerr(_("finder.notFound", searchString), commandline.FORCE_SINGLELINE);
- },
-
- /**
- * Repeats the previous view search.
- *
- * @param {boolean} reverse Search in the reverse direction to the previous
- * search.
- */
- searchViewAgain: function searchViewAgain(reverse) {
- function echo(str) {
- this.timeout(function () {
- commandline.echo(str, commandline.HL_WARNINGMSG, commandline.APPEND_TO_MESSAGES | commandline.FORCE_SINGLELINE);
- }, 0);
- }
-
- if (reverse) {
- if (this._lastSearchIndex == 0) {
- this._lastSearchIndex = this._lastSearchView.length - 1;
- echo(_("finder.atTop"));
- }
- else
- this._lastSearchIndex = this._lastSearchIndex - 1;
- }
- else {
- if (this._lastSearchIndex == (this._lastSearchView.length - 1)) {
- this._lastSearchIndex = 0;
- echo(_("finder.atBottom"));
- }
- else
- this._lastSearchIndex = this._lastSearchIndex + 1;
- }
-
- // TODO: Implement for "?" --ken
- commandline.echo("/" + this._lastSearchString, null, commandline.FORCE_SINGLELINE);
- this.focusTrack(this._lastSearchView.getItemByIndex(this._lastSearchIndex));
-
- },
-
- /**
- * The search dialog keypress callback.
- *
- * @param {string} str The contents of the search dialog.
- */
- onSearchKeyPress: function onSearchKeyPress(str) {
- if (options["incsearch"])
- this.searchView(str);
- },
-
- /**
- * The search dialog submit callback.
- *
- * @param {string} str The contents of the search dialog.
- */
- onSearchSubmit: function onSearchSubmit(str) {
- this.searchView(str);
- },
-
- /**
- * The search dialog cancel callback.
- */
- onSearchCancel: function onSearchCancel() {
- // TODO: restore the view state if altered by an 'incsearch' search
- },
-
- /**
- * Returns an array of all available playlists.
- *
- * @returns {[sbIMediaList]}
- */
- getPlaylists: function getPlaylists() {
- let mainLibrary = LibraryUtils.mainLibrary;
- let playlists = [mainLibrary];
- let listener = {
- onEnumerationBegin: function () { },
- onEnumerationEnd: function () { },
- onEnumeratedItem: function (list, item) {
- // FIXME: why are there null items and duplicates?
- if (!playlists.some(list => list.name == item.name) && item.name != null)
- playlists.push(item);
- return Ci.sbIMediaListEnumerationListener.CONTINUE;
- }
- };
-
- mainLibrary.enumerateItemsByProperty("http://songbirdnest.com/data/1.0#isList", "1", listener);
-
- return playlists;
- },
-
- /**
- * Plays the media item at *index* in *playlist*.
- *
- * @param {sbIMediaList} playlist
- * @param {number} index
- */
- playPlaylist: function playPlaylist(playlist, index) {
- gMM.sequencer.playView(playlist.createView(), index);
- },
-
- /**
- * Returns an array of all available media pages.
- *
- * @returns {[sbIMediaPageInfo]}
- */
- getMediaPages: function getMediaPages() {
- let list = SBGetBrowser().currentMediaPage.mediaListView.mediaList;
- let pages = services.mediaPageManager.getAvailablePages(list);
- return ArrayConverter.JSArray(pages).map(page => page.QueryInterface(Ci.sbIMediaPageInfo));
- },
-
- /**
- * Loads the specified media page into *view* with the given *list* of
- * media items.
- *
- * @param {sbIMediaPage} page
- * @param {sbIMediaList} list
- * @param {sbIMediaView} view
- */
- loadMediaPage: function loadMediaPage(page, list, view) {
- services.mediaPageManager.setPage(list, page);
- SBGetBrowser().loadMediaList(list, null, null, view, null);
- },
-
- /**
- * Applys the specified *rating* to *mediaItem*.
- *
- * @param {sbIMediaItem} mediaItem The media item to rate.
- * @param {number} rating The star rating (1-5).
- */
- rateMediaItem: function rateMediaItem(mediaItem, rating) {
- mediaItem.setProperty(SBProperties.rating, rating);
- },
-
- // TODO: add more fields, and generate the list dynamically. PT should the
- // available fields reflect only the visible view fields or offer others? --djk
- /**
- * Sorts the current media view by *field* in the order specified by
- * *ascending*.
- *
- * @param {string} field The sort field.
- * @param {boolean} ascending If true sort in ascending order, otherwise in
- * descending order.
- */
- sortBy: function sortBy(field, ascending) {
- let order = ascending ? "a" : "d";
- let properties = services.MutablePropertyArray();
- properties.strict = false;
-
- switch (field) {
- case "title":
- properties.appendProperty(SBProperties.trackName, order);
- break;
- case "time":
- properties.appendProperty(SBProperties.duration, order);
- break;
- case "artist":
- properties.appendProperty(SBProperties.artistName, order);
- break;
- case "album":
- properties.appendProperty(SBProperties.albumName, order);
- break;
- case "genre":
- properties.appendProperty(SBProperties.genre, order);
- break;
- case "rating":
- properties.appendProperty(SBProperties.rating, order);
- break;
- default:
- properties.appendProperty(SBProperties.trackName, order);
- break;
- }
-
- this._currentView.setSort(properties);
- }
-}, {
-}, {
- modes: function initModes(dactyl, modules, window) {
- modes.addMode("SEARCH_VIEW", {
- description: "Search View mode",
- bases: [modes.COMMAND_LINE],
- });
- modes.addMode("SEARCH_VIEW_FORWARD", {
- description: "Forward Search View mode",
- bases: [modes.SEARCH_VIEW]
- });
- modes.addMode("SEARCH_VIEW_BACKWARD", {
- description: "Backward Search View mode",
- bases: [modes.SEARCH_VIEW]
- });
-
- },
- commandline: function initCommandline() {
- player.CommandMode = Class("CommandSearchViewMode", modules.CommandMode, {
- init: function init(mode) {
- this.mode = mode;
- init.supercall(this);
- },
-
- historyKey: "search-view",
-
- get prompt() {
- return this.mode === modules.modes.SEARCH_VIEW_BACKWARD ? "?" : "/";
- },
-
- get onCancel() { return player.closure.onSearchCancel; },
- get onChange() { return player.closure.onSearchKeyPress; },
- get onSubmit() { return player.closure.onSearchSubmit; }
- });
- },
- commands: function initCommands() {
- commands.add(["f[ilter]"],
- "Filter tracks based on keywords {genre/artist/album/track}",
- function (args) {
- let view = LibraryUtils.createStandardMediaListView(LibraryUtils.mainLibrary, args.literalArg);
-
- dactyl.assert(view.length, "No matching tracks");
-
- SBGetBrowser().loadMediaList(LibraryUtils.mainLibrary, null, null, view,
- "chrome://songbird/content/mediapages/filtersPage.xul");
- // TODO: make this player.focusTrack work ?
- player.focusTrack(view.getItemByIndex(0));
- }, {
- argCount: "1",
- literal: 0
- //completer: function (context, args) {
- // completion.tracks(context, args);
- //}
- });
-
- commands.add(["load"],
- "Load a playlist",
- function (args) {
- let arg = args.literalArg;
-
- if (arg) {
- // load the selected playlist/smart playlist
- for ([, playlist] in Iterator(player.getPlaylists())) {
- if (util.compareIgnoreCase(arg, playlist.name) == 0) {
- SBGetBrowser().loadMediaList(playlist);
- player.focusTrack(player._currentView.getItemByIndex(0));
- return;
- }
- }
- dactyl.echoerr(_("error.invalidArgument", arg));
- }
- else {
- // load main library if there are no args
- _SBShowMainLibrary();
- }
- }, {
- argCount: "?",
- completer: function (context) {
- completion.playlist(context);
- },
- literal: 0
- });
-
- // TODO: better off as a single command (:player play) or cmus compatible (:player-play)? --djk
- commands.add(["playerp[lay]"],
- "Play track",
- function () { player.play(); });
-
- commands.add(["playerpa[use]"],
- "Pause/unpause track",
- function () { player.togglePlayPause(); });
-
- commands.add(["playern[ext]"],
- "Play next track",
- function (args) { player.next(Math.max(args.count, 1)); },
- { count: true });
-
- commands.add(["playerpr[ev]"],
- "Play previous track",
- function (args) { player.previous(Math.max(args.count, 1)); },
- { count: true });
-
- commands.add(["players[top]"],
- "Stop track",
- function () { player.stop(); });
-
- commands.add(["see[k]"],
- "Seek to a track position",
- function (args) {
- let arg = args[0];
-
- // intentionally supports 999:99:99
- dactyl.assert(/^[+-]?(\d+[smh]?|(\d+:\d\d:|\d+:)?\d{2})$/.test(arg),
- _("error.invalidArgument", arg));
-
- function ms(t, m) {
- return Math.abs(parseInt(t, 10) * { s: 1000, m: 60000, h: 3600000 }[m]);
- }
-
- if (/:/.test(arg)) {
- let [seconds, minutes, hours] = arg.split(":").reverse();
- hours = hours || 0;
- var value = ms(seconds, "s") + ms(minutes, "m") + ms(hours, "h");
- }
- else {
- if (!/[smh]/.test(arg.substr(-1)))
- arg += "s"; // default to seconds
-
- value = ms(arg.substring(arg, arg.length - 1), arg.substr(-1));
- }
-
- if (/^[-+]/.test(arg))
- arg[0] == "-" ? player.seekBackward(value) : player.seekForward(value);
- else
- player.seekTo(value);
-
- },
- { argCount: "1" });
-
- commands.add(["mediav[iew]"],
- "Change the current media view",
- function (args) {
- // FIXME: is this a SB restriction? --djk
- dactyl.assert(SBGetBrowser().currentMediaPage,
- "Exxx: Can only set the media view from the media tab"); // XXX
-
- let arg = args[0];
-
- if (arg) {
- for ([, page] in Iterator(player.getMediaPages())) {
- if (util.compareIgnoreCase(arg, page.contentTitle) == 0) {
- player.loadMediaPage(page, SBGetBrowser().currentMediaListView.mediaList,
- SBGetBrowser().currentMediaListView);
- return;
- }
- }
- dactyl.echoerr(_("error.invalidArgument", arg));
- }
- }, {
- argCount: "1",
- completer: function (context) {
- completion.mediaView(context);
- },
- literal: 0
- });
-
- commands.add(["sort[view]"],
- "Sort the current media view",
- function (args) {
- player.sortBy(args[0], args["-order"] == "up");
- }, {
- argCount: "1",
- completer: function (context) {
- completion.mediaListSort(context);
- },
- options: [
- {
- names: ["-order", "-o"], type: CommandOption.STRING,
- default: "up",
- description: "Specify the sorting order of the given field",
- validator: function (arg) {
- return /^(up|down)$/.test(arg);
- },
- completer: function () {
- return [["up", "Sort in ascending order"], ["down", "Sort in descending order"]];
- }
- }
- ]
- });
-
- // FIXME: use :add -q like cmus? (not very vim-like are it's multi-option commands) --djk
- commands.add(["qu[eue]"],
- "Queue tracks by artist/album/track",
- function (args) {
- let properties = services.MutablePropertyArray();
-
- // args
- switch (args.length) {
- case 3:
- properties.appendProperty(SBProperties.trackName, args[2]);
- case 2:
- properties.appendProperty(SBProperties.albumName, args[1]);
- case 1:
- properties.appendProperty(SBProperties.artistName, args[0]);
- break;
- default:
- break;
- }
-
- let library = LibraryUtils.mainLibrary;
- let mainView = library.createView();
- gMM.sequencer.playView(mainView,
- mainView.getIndexForItem(library.getItemsByProperties(properties).queryElementAt(0, Ci.sbIMediaItem)));
- player.focusPlayingTrack();
- }, {
- argCount: "+",
- completer: function (context, args) {
- if (args.completeArg == 0)
- completion.artist(context);
- else if (args.completeArg == 1)
- completion.album(context, args[0]);
- else if (args.completeArg == 2)
- completion.song(context, args[0], args[1]);
- }
- });
-
- // TODO: maybe :vol! could toggle mute on/off? --djk
- commands.add(["vol[ume]"],
- "Set the volume",
- function (args) {
- let arg = args[0];
-
- dactyl.assert(arg, _("error.argumentRequired"));
- dactyl.assert(/^[+-]?\d+$/.test(arg), _("error.trailingCharacters"));
-
- let level = parseInt(arg, 10) / 100;
-
- if (/^[+-]/.test(arg))
- level = player.volume + level;
-
- player.volume = Math.constrain(level, 0, 1);
- },
- { argCount: "1" });
- },
- completion: function initCompletion() {
- completion.album = function album(context, artist) {
- context.title = ["Album"];
- context.completions = [[v, ""] for ([, v] in Iterator(library.getAlbums(artist)))];
- };
-
- completion.artist = function artist(context) {
- context.title = ["Artist"];
- context.completions = [[v, ""] for ([, v] in Iterator(library.getArtists()))];
- };
-
- completion.playlist = function playlist(context) {
- context.title = ["Playlist", "Type"];
- context.keys = { text: "name", description: "type" };
- context.completions = player.getPlaylists();
- };
-
- completion.mediaView = function mediaView(context) {
- context.title = ["Media View", "URL"];
- context.anchored = false;
- context.keys = { text: "contentTitle", description: "contentUrl" };
- context.completions = player.getMediaPages();
- };
-
- completion.mediaListSort = function mediaListSort(context) {
- context.title = ["Media List Sort Field", "Description"];
- context.anchored = false;
- context.completions = [["title", "Track name"], ["time", "Duration"], ["artist", "Artist name"],
- ["album", "Album name"], ["genre", "Genre"], ["rating", "Rating"]]; // FIXME: generate this list dynamically - see #sortBy
- };
-
- completion.song = function album(context, artist, album) {
- context.title = ["Song"];
- context.completions = [[v, ""] for ([, v] in Iterator(library.getTracks(artist, album)))];
- };
- },
- mappings: function initMappings() {
- mappings.add([modes.PLAYER],
- ["x"], "Play track",
- function () { ex.playerplay(); });
-
- mappings.add([modes.PLAYER],
- ["z"], "Previous track",
- function ({ count }) { ex.playerprev({ "#": count }); },
- { count: true });
-
- mappings.add([modes.PLAYER],
- ["c"], "Pause/unpause track",
- function () { ex.playerpause(); });
-
- mappings.add([modes.PLAYER],
- ["b"], "Next track",
- function ({ count }) { ex.playernext({ "#": count }); },
- { count: true });
-
- mappings.add([modes.PLAYER],
- ["v"], "Stop track",
- function () { ex.playerstop(); });
-
- mappings.add([modes.PLAYER],
- ["Q"], "Queue tracks by artist/album/track",
- function () { commandline.open(":", "queue ", modes.EX); });
-
- mappings.add([modes.PLAYER],
- ["f"], "Loads current view filtered by the keywords",
- function () { commandline.open(":", "filter ", modes.EX); });
-
- mappings.add([modes.PLAYER],
- ["i"], "Select current track",
- function () { gSongbirdWindowController.doCommand("cmd_find_current_track"); });
-
- mappings.add([modes.PLAYER],
- ["s"], "Toggle shuffle",
- function () { player.toggleShuffle(); });
-
- mappings.add([modes.PLAYER],
- ["r"], "Toggle repeat",
- function () { player.toggleRepeat(); });
-
- mappings.add([modes.PLAYER],
- ["h", "<Left>"], "Seek -10s",
- function ({ count} ) { player.seekBackward(Math.max(1, count) * 10000); },
- { count: true });
-
- mappings.add([modes.PLAYER],
- ["l", "<Right>"], "Seek +10s",
- function ({ count} ) { player.seekForward(Math.max(1, count) * 10000); },
- { count: true });
-
- mappings.add([modes.PLAYER],
- ["H", "<S-Left>"], "Seek -1m",
- function ({ count }) { player.seekBackward(Math.max(1, count) * 60000); },
- { count: true });
-
- mappings.add([modes.PLAYER],
- ["L", "<S-Right>"], "Seek +1m",
- function ({ count }) { player.seekForward(Math.max(1, count) * 60000); },
- { count: true });
-
- mappings.add([modes.PLAYER],
- ["=", "+"], "Increase volume by 5% of the maximum",
- function () { player.increaseVolume(); });
-
- mappings.add([modes.PLAYER],
- ["-"], "Decrease volume by 5% of the maximum",
- function () { player.decreaseVolume(); });
-
- mappings.add([modes.PLAYER],
- ["/"], "Search forward for a track",
- function () { player.CommandMode(modes.SEARCH_VIEW_FORWARD).open(); });
-
- mappings.add([modes.PLAYER],
- ["n"], "Find the next track",
- function () { player.searchViewAgain(false); });
-
- mappings.add([modes.PLAYER],
- ["N"], "Find the previous track",
- function () { player.searchViewAgain(true); });
-
- for (let i in util.range(0, 6)) {
- let (rating = i) {
- mappings.add([modes.PLAYER],
- ["<C-" + rating + ">"], "Rate the current media item " + rating,
- function () {
- let item = gMM.sequencer.currentItem || this._currentView.selection.currentMediaItem; // XXX: a bit too magic
- if (item)
- player.rateMediaItem(item, rating);
- else
- dactyl.beep();
- }
- );
- };
- }
- },
- options: function initOptions() {
- options.add(["repeat"],
- "Set the playback repeat mode",
- "number", 0,
- {
- setter: function (value) {
- return gMM.sequencer.repeatMode = value;
- },
- getter: function () { return gMM.sequencer.repeatMode; },
- completer: function () {
- return [
- ["0", "Repeat none"],
- ["1", "Repeat one"],
- ["2", "Repeat all"]
- ];
- }
- });
-
- options.add(["shuffle"],
- "Play tracks in shuffled order",
- "boolean", false,
- {
- setter: function (value) {
- return gMM.sequencer.mode = value ? gMM.sequencer.MODE_SHUFFLE : gMM.sequencer.MODE_FORWARD;
- },
- getter: function () {
- return gMM.sequencer.mode == gMM.sequencer.MODE_SHUFFLE;
- }
- });
- }
-});
-
-// vim: set fdm=marker sw=4 sts=4 ts=8 et:
diff --git a/melodactyl/defaults/preferences/dactyl.js b/melodactyl/defaults/preferences/dactyl.js
deleted file mode 100644
index 077178a9..00000000
--- a/melodactyl/defaults/preferences/dactyl.js
+++ /dev/null
@@ -1,6 +0,0 @@
-pref("extensions.dactyl.name", "melodactyl");
-pref("extensions.dactyl.appName", "Melodactyl");
-pref("extensions.dactyl.idName", "MELODACTYL");
-pref("extensions.dactyl.fileExt", "melo");
-pref("extensions.dactyl.host", "Songbird");
-pref("extensions.dactyl.hostbin", "songbird");
diff --git a/melodactyl/install.rdf b/melodactyl/install.rdf
deleted file mode 100644
index 72300720..00000000
--- a/melodactyl/install.rdf
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:em="http://www.mozilla.org/2004/em-rdf#"
- xmlns:songbird="http://www.songbirdnest.com/2007/addon-metadata-rdf#">
- <Description about="urn:mozilla:install-manifest"
- em:id="melodactyl@dactyl.googlecode.com"
- em:type="2"
- em:name="Melodactyl"
- em:version="0.1a1pre"
- em:description="Songbird for Vim and CMus junkies."
- em:creator="Prathyush Thota"
- em:homepageURL="http://5digits.org/"
- em:iconURL="chrome://melodactyl/skin/icon.png"
- em:optionsURL="chrome://dactyl/content/preferences.xul">
- <em:targetApplication>
- <Description>
- <em:id>songbird@songbirdnest.com</em:id>
- <em:minVersion>1.8.0</em:minVersion>
- <em:maxVersion>1.9.*</em:maxVersion>
- </Description>
- </em:targetApplication>
- </Description>
-</RDF>
-
-<!-- vim: set fdm=marker sw=4 ts=4 et: -->
diff --git a/melodactyl/locale/en-US/all.xml b/melodactyl/locale/en-US/all.xml
deleted file mode 100644
index 7d838b98..00000000
--- a/melodactyl/locale/en-US/all.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<include href="player" tag="player.html" insertafter="intro.html"/>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/melodactyl/locale/en-US/autocommands.xml b/melodactyl/locale/en-US/autocommands.xml
deleted file mode 100644
index 154ca6b5..00000000
--- a/melodactyl/locale/en-US/autocommands.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<dl tag="autocommand-list" replace="autocommand-list">
- <dt>BookmarkAdd</dt> <dd>Triggered after a page is bookmarked</dd>
- <dt>ColorScheme</dt> <dd>Triggered after a color scheme has been loaded</dd>
- <dt>DOMLoad</dt> <dd>Triggered when a page's DOM content has fully loaded</dd>
- <dt>DownloadPost</dt> <dd>Triggered when a download has completed</dd>
- <dt>Fullscreen</dt> <dd>Triggered when the player's fullscreen state changes</dd>
- <dt>LocationChange</dt><dd>Triggered when changing tabs or when navigating to a new location</dd>
- <dt>PageLoadPre</dt> <dd>Triggered after a page load is initiated</dd>
- <dt>PageLoad</dt> <dd>Triggered when a page gets (re)loaded/opened</dd>
- <dt>ShellCmdPost</dt> <dd>Triggered after executing a shell command with <ex>:!</ex>#{cmd}</dd>
- <dt>TrackChangePre</dt><dd>Triggered before a playing track is changed</dd>
- <dt>TrackChange</dt> <dd>Triggered after a playing track has changed</dd>
- <dt>ViewChangePre</dt> <dd>Triggered before a sequencer view is changed</dd>
- <dt>ViewChange</dt> <dd>Triggered after a sequencer view is changed</dd>
- <dt>StreamStart</dt> <dd>Triggered after a stream has started</dd>
- <dt>StreamPause</dt> <dd>Triggered after a stream has paused</dd>
- <dt>StreamEnd</dt> <dd>Triggered after a stream has ended</dd>
- <dt>StreamStop</dt> <dd>Triggered after a stream has stopped</dd>
- <dt>Enter</dt> <dd>Triggered after Songbird starts</dd>
- <dt>LeavePre</dt> <dd>Triggered before exiting Songbird, just before destroying each module</dd>
- <dt>Leave</dt> <dd>Triggered before exiting Songbird</dd>
-</dl>
-
-<dl tag="autocommand-args" replace="autocommand-args">
- <dt>&lt;url></dt> <dd>The URL against which the event was selected.</dd>
- <dt>&lt;title></dt> <dd>The page, bookmark or download title.</dd>
- <dt>&lt;doc></dt> <dd>The document for which the event occurred. Only for <em>DOMLoad</em>, <em>PageLoad</em> and <em>PageLoadPre</em>.</dd>
- <dt>&lt;tab></dt> <dd>The tab in which the event occurred. Only for <em>DOMLoad</em>, <em>PageLoad</em> and <em>PageLoadPre</em>.</dd>
- <dt>&lt;tags></dt> <dd>The tags applied to <em>&lt;url></em>. Only for <em>BookmarkAdd</em>.</dd>
- <dt>&lt;keyword></dt><dd>The keywords applied to the bookmark. Only for <em>BookmarkAdd</em>.</dd>
- <dt>&lt;icon></dt> <dd>The icon associated with <em>&lt;url></em>. Only for <em>BookmarkAdd</em>.</dd>
- <dt>&lt;size></dt> <dd>The size of a downloaded file. Only for <em>DownloadPost</em>.</dd>
- <dt>&lt;file></dt> <dd>The target destination of a download. Only for <em>DownloadPost</em>.</dd>
- <dt>&lt;state></dt> <dd>The new fullscreen state. Only for <em>Fullscreen</em>.</dd>
- <dt>&lt;name></dt> <dd>The color scheme name. Only for <em>ColorScheme</em>.</dd>
- <dt>&lt;view></dt> <dd>The new sequencer view. Only for <em>ViewChangePre</em> and <em>ViewChange</em>.</dd>
- <dt>&lt;track></dt> <dd>The new media track. Only for <em>TrackChangePre</em>, <em>TrackChange</em> and <em>Stream</em>.</dd>
-</dl>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/melodactyl/locale/en-US/browsing.xml b/melodactyl/locale/en-US/browsing.xml
deleted file mode 100644
index 400d475d..00000000
--- a/melodactyl/locale/en-US/browsing.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<span replace="w"/>
-<span replace="W"/>
-<span replace=":wc"/>
-<span replace=":winon"/>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/melodactyl/locale/en-US/gui.xml b/melodactyl/locale/en-US/gui.xml
deleted file mode 100644
index c4d308c8..00000000
--- a/melodactyl/locale/en-US/gui.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<item replace=":sbcl">
- <tags>:dpcl :dpclose</tags>
- <spec>:dpcl<oa>ose</oa> <a>pane</a></spec>
- <description>
- <p>Close the specified display pane.</p>
- </description>
-</item>
-
-<item replace=":sbope">
- <tags>:dpope :dpopen :dp :dpane :displayp :displaypane</tags>
- <spec>:displaypane <a>pane</a></spec>
- <description>
- <p>
- Open the specified display pane. <a>pane</a> is any of
- "leftservice", "bottomservice", "bottomcontent" or "rightsidebar".
- </p>
- </description>
-</item>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/melodactyl/locale/en-US/intro.xml b/melodactyl/locale/en-US/intro.xml
deleted file mode 100644
index 6d9eff76..00000000
--- a/melodactyl/locale/en-US/intro.xml
+++ /dev/null
@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<p replace="intro-text">
- <link topic="&dactyl.apphome;">&dactyl.appName;</link>
- is a free media player add-on for &dactyl.host;, which combines the best
- features of the <link topic="http://cmus.sourceforge.net">CMus</link> music
- player and the <link topic="http://www.vim.org">Vim</link> text editor.
-</p>
-
-<!-- TODO: make Melodactyl specific -->
-<ol replace="topics-list">
- <!--
- <li>
- <link topic="tutorial">Quick-start tutorial</link>:
- A quick-start tutorial for new users.
- </li>
- -->
- <li>
- <link topic="starting">Starting &dactyl.appName;</link>:
- How &dactyl.appName; starts up, where it reads the config file, etc.
- </li>
- <li>
- <link topic="player">Player mode</link>:
- Interacting with the media player.
- </li>
- <li>
- <link topic="browsing">Browsing</link>:
- Basic key mappings and commands needed for a browsing
- session (how to open a web page, go back in history, etc.)
- </li>
- <li>
- <link topic="buffer">Buffer</link>:
- Operations on the current document (scrolling, copying text,
- etc.)
- </li>
- <li>
- <link topic="cmdline">Command Line mode</link>:
- Command-line editing.
- </li>
- <li>
- <link topic="editing">Editing text</link>:
- Text area and input field editing.
- </li>
- <li>
- <link topic="options">Options</link>:
- A description of all options.
- </li>
- <li>
- <link topic="pattern">Text search commands</link>:
- Searching for text in the current buffer.
- </li>
- <li>
- <link topic="tabs">Tabs</link>:
- Managing your tabbed browsing session.
- </li>
- <li>
- <link topic="hints">Hints</link>:
- Selecting hyperlinks and other page elements.
- </li>
- <li>
- <link topic="map">Keyboard shortcuts and commands</link>:
- Defining new key mappings, abbreviations and user commands.
- </li>
- <li>
- <link topic="eval">Expression evaluation</link>:
- Executing JavaScript.
- </li>
- <li>
- <link topic="marks">Marks</link>:
- Using bookmarks, QuickMarks, history and local marks.
- </li>
- <li>
- <link topic="repeat">Repeating commands</link>:
- Using macros to repeat recurring workflows.
- </li>
- <li>
- <link topic="autocommands">Automatic commands</link>:
- Automatically executing code on certain events.
- </li>
- <li>
- <link topic="print">Printing</link>:
- Printing pages.
- </li>
- <li>
- <link topic="gui">&dactyl.appName;'s GUI</link>:
- Accessing &dactyl.host; menus, dialogs and the display panels.
- </li>
- <li>
- <link topic="styling">Styling the GUI and web pages</link>:
- Changing the styling of content pages and &dactyl.appName; itself.
- </li>
- <li>
- <link topic="message">Error and informational messages</link>:
- A description of informational and error messages.
- </li>
- <li>
- <link topic="developer">Developer information</link>:
- How to write plugins and documentation.
- </li>
- <li>
- <link topic="various">Various commands</link>:
- Other help which doesn't readily fit into any other category.
- </li>
- <li>
- <link topic="plugins">Plugins</link>:
- Documentation for any plugins you have installed.
- </li>
- <li>
- <link topic="index">Index</link>:
- An index of all commands and options.
- </li>
-</ol>
-
-<!-- TODO: make Melodactyl specific -->
-<ul replace="features-list">
- <li>Vim-like keybindings (<k>h</k>, <k>j</k>, <k>gg</k>, <k>ZZ</k>, <k name="C-f"/>, etc.)</li>
- <li>Ex commands (<ex>:quit</ex>, <ex>:open www.foo.com</ex>, …)</li>
- <li>Tab completion for all commands, highly configurable via <o>wildmode</o>, <o>autocomplete</o>, …</li>
- <li>Hit-a-hint like navigation of links (start with <k>f</k> to follow a link)</li>
- <li>Advanced completion of bookmark and history URLs</li>
- <li>Vim-like status line with a Wget-like progress bar</li>
- <li>Minimal GUI (easily hide superfluous menubar and toolbar with <se opt="guioptions"/>)</li>
- <li>Ability to <ex>:source</ex> JavaScript, CSS, and &dactyl.appName; command files</li>
- <li>Easy quick searches (see <ex>:open</ex>)</li>
- <li>Count supported for many commands (<em>3</em><k name="C-o"/> will go back 3 pages)</li>
- <li>Visual bell for errors (<o>visualbell</o>)</li>
- <li>Marks support (<k>m</k><em>a</em> to set mark a, <k>'</k><em>a</em> to jump to it)</li>
- <li><link topic="quickmarks">QuickMark</link> support</li>
- <li><ex>:map</ex>, <ex>:command</ex>, <ex>:normal</ex>, and <t>macros</t></li>
- <li><link topic="i_&lt;C-i>">Editing of text fields</link> with an <link topic="'editor'">external editor</link></li>
- <li>AutoCommands to execute actions on certain events</li>
- <li>A comprehensive help system, explaining all commands, mappings, options, and plugins</li>
-</ul>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/melodactyl/locale/en-US/map.xml b/melodactyl/locale/en-US/map.xml
deleted file mode 100644
index e8b1e129..00000000
--- a/melodactyl/locale/en-US/map.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<dl replace=":command-complete-arg-list">
- <dt>abbreviation</dt> <dd>abbreviations</dd>
- <dt>altstyle</dt> <dd>alternate author style sheets</dd>
- <dt>bookmark</dt> <dd>bookmarks</dd>
- <dt>buffer</dt> <dd>buffers</dd>
- <dt>charset</dt> <dd>character sets</dd>
- <dt>color</dt> <dd>color schemes</dd>
- <dt>command</dt> <dd>Ex commands</dd>
- <dt>dialog</dt> <dd>&dactyl.host; dialogs</dd>
- <dt>displaypane</dt> <dd>display panes</dd>
- <dt>dir</dt> <dd>directories</dd>
- <dt>environment</dt> <dd>environment variables</dd>
- <dt>event</dt> <dd>autocommand events</dd>
- <dt>extension</dt> <dd>installed extensions</dd>
- <dt>file</dt> <dd>files</dd>
- <dt>help</dt> <dd>help tags</dd>
- <dt>highlight</dt> <dd>highlight groups</dd>
- <dt>history</dt> <dd>browsing history</dd>
- <dt>javascript</dt> <dd>JavaScript expressions</dd>
- <dt>macro</dt> <dd>named macros</dd>
- <dt>mapping</dt> <dd>user mappings</dd>
- <dt>mark</dt> <dd>local page marks</dd>
- <dt>mediaview</dt> <dd>media views</dd>
- <dt>mediasort</dt> <dd>media sort fields</dd>
- <dt>menu</dt> <dd>menu items</dd>
- <dt>option</dt> <dd>&dactyl.appName; options</dd>
- <dt>playlist</dt> <dd>play lists</dd>
- <dt>preference</dt> <dd>&dactyl.host; preferences</dd>
- <dt>qmark</dt> <dd>quick marks</dd>
- <dt>runtime</dt> <dd>runtime paths</dd>
- <dt>search</dt> <dd>search engines and keywords</dd>
- <dt>shellcmd</dt> <dd>shell commands</dd>
- <dt>song</dt> <dd>songs</dd>
- <dt>toolbar</dt> <dd>toolbars</dd>
- <dt>url</dt> <dd>URLs</dd>
- <dt>usercommand</dt> <dd>user commands</dd>
- <dt>custom,<a>thing</a></dt><dd>custom completion, provided by <a>thing</a></dd>
-</dl>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/melodactyl/locale/en-US/messages.properties b/melodactyl/locale/en-US/messages.properties
deleted file mode 100644
index f5ec2170..00000000
--- a/melodactyl/locale/en-US/messages.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-player.preTrackChange-1 = Before track changed: %S
-player.postTrackChange-1 = Track changed: %S
-player.preViewChange-1 = Before view changed: %S
-player.postViewChange-1 = View changed: %S
-player.trackStart-1 = Track started: %S
-player.trackPause-1 = Track paused: %S
-player.trackEnd-1 = Track ended: %S
-player.trackStop-1 = Track stopped: %S
-
-# vim:se ft=jproperties tw=0:
diff --git a/melodactyl/locale/en-US/player.xml b/melodactyl/locale/en-US/player.xml
deleted file mode 100644
index ef955186..00000000
--- a/melodactyl/locale/en-US/player.xml
+++ /dev/null
@@ -1,328 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE document SYSTEM "dactyl://content/dtd">
-
-<document
- name="player"
- title="&dactyl.appName; Player mode"
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<h1 tag="player-mode player">Player mode</h1>
-<toc start="2"/>
-
-<p>
- The following features apply to Player mode which is activated when the
- media tab has focus.
-</p>
-
-<h2 tag="playing-tracks">Playing tracks</h2>
-
-<item>
- <tags>p_x :playerp :playerplay</tags>
- <spec>:<oa>count</oa>playerp<oa>lay</oa></spec>
- <spec><oa>count</oa>x</spec>
- <description>
- <p>
- Play the current track.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_z :playerpr :playerprev</tags>
- <spec>:<oa>count</oa>playerpr<oa>ev</oa></spec>
- <spec><oa>count</oa>z</spec>
- <description>
- <p>
- Play the previous track.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_b :playern :playernext</tags>
- <spec>:playern<oa>ext</oa></spec>
- <spec>b</spec>
- <description>
- <p>
- Play the next track.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_c :playerpa :playerpause</tags>
- <spec>:playerpa<oa>use</oa></spec>
- <spec>c</spec>
- <description>
- <p>
- Pause/unpause the current track.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_v :playerps :playerstop</tags>
- <spec>:playerps<oa>top</oa></spec>
- <spec>v</spec>
- <description>
- <p>
- Stop playing the current track.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_s</tags>
- <spec>s</spec>
- <description>
- <p>
- Toggle shuffle mode.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_r</tags>
- <spec>r</spec>
- <description>
- <p>
- Toggle repeat mode.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_i</tags>
- <spec>i</spec>
- <description>
- <p>
- Select the currently playing track.
- </p>
- </description>
-</item>
-
-<h2 tag="queue queueing">Queueing tracks</h2>
-
-<item>
- <tags>p_Q :qu :queue</tags>
- <spec>:qu<oa>eue</oa> <a>artist</a> <oa>album</oa> <oa>track</oa></spec>
- <spec>Q</spec>
- <description>
- <p>
- Queue tracks by artist/album/track. If only <a>artist</a> is
- specified then all tracks for that artist are played in album
- order. If <oa>album</oa> is also specified then all tracks for that
- album are played. A specific track can be specified with
- <oa>track</oa>.
- </p>
- </description>
-</item>
-
-<h2 tag="filter filtering">Filtering the library</h2>
-
-<item>
- <tags>p_f :f :filter</tags>
- <spec>:f<oa>ilter</oa> <a>keywords</a></spec>
- <spec>f</spec>
- <description>
- <p>
- Filter and show the tracks as a view. The tracks are filtered by
- the <a>keywords</a> provided as arguments. This text search applies
- over the default filter properties, namely: Genre, Artist, Album
- and Track.
- </p>
- </description>
-</item>
-
-<h2 tag="seeking">Seeking to a track position</h2>
-
-<item>
- <tags><![CDATA[p_<Left> p_h]]></tags>
- <spec><oa>count</oa>h</spec>
- <description>
- <p>
- Seek +10s.
- </p>
- </description>
-</item>
-
-<item>
- <tags><![CDATA[p_<Right> p_l]]></tags>
- <spec><oa>count</oa>l</spec>
- <description>
- <p>
- Seek -10s.
- </p>
- </description>
-</item>
-
-<item>
- <tags><![CDATA[p_<S-Left> p_H]]></tags>
- <spec><oa>count</oa>H</spec>
- <description>
- <p>
- Seek +1m.
- </p>
- </description>
-</item>
-
-<item>
- <tags><![CDATA[p_<S-Right> p_L]]></tags>
- <spec><oa>count</oa>L</spec>
- <description>
- <p>
- Seek -1m.
- </p>
- </description>
-</item>
-
-<item>
- <tags>:see :seek</tags>
- <spec>:see<oa>k</oa> <a>[HH:]MM:SS]</a></spec>
- <spec>:see<oa>k</oa> +<a>time[hms]</a> | -<a>time[hms]</a></spec>
- <description>
- <p>
- Seek to an absolute or relative position in a track. The position
- can be given in seconds (s), minutes (m), or hours (h). If the unit
- is not specified then seconds is assumed. The position is absolute
- unless the value is prefixed with "-" or "+".
- </p>
- <p>
- Positions may also be specified in <a>[HH:]MM:SS</a> format.
- </p>
- </description>
-</item>
-
-<h2 tag="volume">Adjusting the volume</h2>
-
-<item>
- <tags>p_+ p_=</tags>
- <spec>+</spec>
- <spec>=</spec>
- <description>
- <p>
- Increase volume by 5% of the maximum.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_-</tags>
- <spec>-</spec>
- <description>
- <p>
- Decrease volume by 5% of the maximum.
- </p>
- </description>
-</item>
-
-<item>
- <tags>:vol :volume</tags>
- <spec>vol<oa>[ume]</oa> <a>value</a></spec>
- <spec>vol<oa>[ume]</oa> +<a>value</a> | -<a>value</a></spec>
- <description>
- <p>
- Set the player volume. <a>value</a> can be an absolute value
- between 0 and 100% or a relative value if prefixed with "-" or "+".
- </p>
- </description>
-</item>
-
-<h2 tag="playlists">Managing playlists</h2>
-
-<item>
- <tags>:load</tags>
- <spec>:load <oa>playlist</oa></spec>
- <description>
- <p>
- Load <a>playlist</a>. If no playlist is specified then the main
- library view is loaded.
- </p>
- </description>
-</item>
-
-<h2 tag="media-view view">Changing media views</h2>
-
-<item>
- <tags>:mediav :mediaview</tags>
- <spec>:mediav<oa>ew</oa> <a>view</a></spec>
- <description>
- <p>
- Change the media view to <a>view</a>. This can only be run when the
- media tab is the current tab.
- </p>
- </description>
-</item>
-
-<h2 tag="search">Search commands</h2>
-
-<item>
- <tags>p_/</tags>
- <spec>/<a>pattern</a></spec>
- <description>
- <p>
- Search forward for a track matching <a>pattern</a> in the visible
- media view.
- </p>
- </description>
-</item>
-
-<!--
-<item>
- <tags>p_?</tags>
- <spec>?<a>pattern</a></spec>
- <description>
- <p>
- Search backwards for a track matching <a>pattern</a> in the visible
- media view.
- </p>
- </description>
-</item>
--->
-
-<item>
- <tags>p_n</tags>
- <spec>n</spec>
- <description>
- <p>
- Find the next track. Repeats the last search. If the search hits
- BOTTOM of the view, it continues from TOP.
- </p>
- </description>
-</item>
-
-<item>
- <tags>p_N</tags>
- <spec>N</spec>
- <description>
- <p>
- Find the previous track. Repeats the last search in the opposite
- direction. If the search hits TOP of the view, it continues from
- BOTTTOM.
- </p>
- </description>
-</item>
-
-<h2 tag="rating">Rating tracks</h2>
-
-<item>
- <tags><![CDATA[p_<C-5> p_<C-4> p_<C-3> p_<C-2> p_<C-1> p_<C-0>]]></tags>
- <spec><![CDATA[<C-0>]]></spec>
- <spec><![CDATA[<C-1>]]></spec>
- <spec><![CDATA[<C-2>]]></spec>
- <spec><![CDATA[<C-3>]]></spec>
- <spec><![CDATA[<C-4>]]></spec>
- <spec><![CDATA[<C-5>]]></spec>
- <description>
- <p>
- Rate the current track with N stars.
- </p>
- </description>
-</item>
-
-</document>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/melodactyl/locale/en-US/tabs.xml b/melodactyl/locale/en-US/tabs.xml
deleted file mode 100644
index 1514253d..00000000
--- a/melodactyl/locale/en-US/tabs.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<span replace=":window"/>
-<span replace=":u"/>
-<span replace=":undoa"/>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/melodactyl/skin/icon.png b/melodactyl/skin/icon.png
deleted file mode 100644
index 3d16d3fc..00000000
--- a/melodactyl/skin/icon.png
+++ /dev/null
Binary files differ
diff --git a/teledactyl/AUTHORS b/teledactyl/AUTHORS
deleted file mode 100644
index f3cc6bb4..00000000
--- a/teledactyl/AUTHORS
+++ /dev/null
@@ -1,11 +0,0 @@
-Main developer/Project founder:
- * Martin Stubenschrott (stubenschrott@vimperator.org)
-
-Inactive/former developers:
- * Daniel Bainton (dpb .AT. driftaway .DOT. org)
-
-Patches:
- * Christian Dietrich (too many to list)
-
-A lot of people contributed to Pentadactyl, which is the basis of Teledactyl, so please refer
-to that AUTHOR file for more contributors.
diff --git a/teledactyl/Makefile b/teledactyl/Makefile
deleted file mode 100644
index 46abb521..00000000
--- a/teledactyl/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#### configuration
-
-NAME = teledactyl
-
-THUNDERBIRD ?= thunderbird
-HOSTAPP ?= $(THUNDERBIRD)
-PROFILEPATHS ?= "$$HOME/.thunderbird" \
- "$$HOME/Library/Thunderbird" \
- "$$APPDATA/Thunderbird" \
- "$$AppData/Thunderbird"
-
-include ../common/Makefile
diff --git a/teledactyl/NEWS b/teledactyl/NEWS
deleted file mode 100644
index e69de29b..00000000
--- a/teledactyl/NEWS
+++ /dev/null
diff --git a/teledactyl/TODO b/teledactyl/TODO
deleted file mode 100644
index 3c8c498e..00000000
--- a/teledactyl/TODO
+++ /dev/null
@@ -1,17 +0,0 @@
-Priority list:
-1-9 as in vim (9=required for next release, 5=would be nice, 1=probably not)
-
-BUGS:
-- several tab related commands like :tab are enabled but don't work
-- stal=1 doesn't work
-
-(recent CVS regressions):
-- 'autoexternal' doesn't work
-
-FEATURES:
-9 check autocmd Events - which are applicable etc.
-9 edit messages with vim
-8 the archives need to be mailbox specific
- - currently it archives mail to the first Archive folder found
-7 :set! mailnews.wraplength=140 or similar
-6 add a feature to show emails from threads under each other like in gmail
diff --git a/teledactyl/bootstrap.js b/teledactyl/bootstrap.js
deleted file mode 120000
index ff1024d5..00000000
--- a/teledactyl/bootstrap.js
+++ /dev/null
@@ -1 +0,0 @@
-../common/bootstrap.js \ No newline at end of file
diff --git a/teledactyl/chrome.manifest b/teledactyl/chrome.manifest
deleted file mode 120000
index 40321439..00000000
--- a/teledactyl/chrome.manifest
+++ /dev/null
@@ -1 +0,0 @@
-../common/chrome.manifest \ No newline at end of file
diff --git a/teledactyl/components/commandline-handler.js b/teledactyl/components/commandline-handler.js
deleted file mode 120000
index aa8427b9..00000000
--- a/teledactyl/components/commandline-handler.js
+++ /dev/null
@@ -1 +0,0 @@
-../../common/components/commandline-handler.js \ No newline at end of file
diff --git a/teledactyl/config.json b/teledactyl/config.json
deleted file mode 100644
index 59825b60..00000000
--- a/teledactyl/config.json
+++ /dev/null
@@ -1,71 +0,0 @@
-{
- "name": "teledactyl",
- "appName": "Teledactyl",
- "idName": "TELEDACTYL",
- "host": "Thunderbird",
- "hostbin": "thunderbird",
-
- "autocommands": {
- "DOMLoad": "Triggered when a page's DOM content has fully loaded",
- "FolderLoad": "Triggered after switching folders in Thunderbird",
- "PageLoadPre": "Triggered after a page load is initiated",
- "PageLoad": "Triggered when a page gets (re)loaded/opened",
- "Enter": "Triggered after Thunderbird starts",
- "Leave": "Triggered before exiting Thunderbird",
- "LeavePre": "Triggered before exiting Thunderbird"
- },
-
- "guioptions": {
- "m": ["MenuBar", ["mail-toolbar-menubar2"]],
- "T": ["Toolbar", ["mail-bar2"]]
- },
-
- "option-defaults": {
- "complete": "f",
- "showtabline": 1,
- "titlestring": "Teledactyl"
- },
-
- "overlays": {
- "chrome://messenger/content/messenger.xul": {
- "features": [
- "hints",
- "mail",
- "marks",
- "addressbook",
- "tabs"
- ],
-
- "guioptions": {
- "f": ["Folder list", ["folderPaneBox", "folderpane_splitter"]],
- "F": ["Folder list header", ["folderPaneHeader"]]
- },
-
- "option-defaults": {
- "guioptions": "bCfrs"
- },
-
- "scripts": [
- "addressbook",
- "mail",
- "tabs"
- ]
- },
-
- "chrome://messenger/content/messengercompose/messengercompose.xul": {
- "is-compose-window": true,
-
- "features": [
- "addressbook"
- ],
-
- "option-defaults": {
- "guioptions": "bCrs"
- },
-
- "scripts": [
- "compose/compose"
- ]
- }
- }
-}
diff --git a/teledactyl/content/addressbook.js b/teledactyl/content/addressbook.js
deleted file mode 100644
index aa90d0ac..00000000
--- a/teledactyl/content/addressbook.js
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2008 by Christian Dietrich <stettberger@dokucode.de>
-//
-// This work is licensed for reuse under an MIT license. Details are
-// given in the LICENSE.txt file included with this file.
-"use strict";
-
-var Addressbook = Module("addressbook", {
- init: function () {
- },
-
- // TODO: add option for a format specifier, like:
- // :set displayname=%l, %f
- generateDisplayName: function (firstName, lastName) {
- if (firstName && lastName)
- return lastName + ", " + firstName;
- else if (firstName)
- return firstName;
- else if (lastName)
- return lastName;
- else
- return "";
- },
-
- getDirectoryFromURI: function (uri) services.rdf.GetResource(uri).QueryInterface(Ci.nsIAbDirectory),
-
- add: function (address, firstName, lastName, displayName) {
- const personalAddressbookURI = "moz-abmdbdirectory://abook.mab";
- let directory = this.getDirectoryFromURI(personalAddressbookURI);
- let card = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance(Ci.nsIAbCard);
-
- if (!address || !directory || !card)
- return false;
-
- card.primaryEmail = address;
- card.firstName = firstName;
- card.lastName = lastName;
- card.displayName = displayName;
-
- return directory.addCard(card);
- },
-
- // TODO: add telephone number support
- list: function (filter, newMail) {
- let addresses = [];
- let dirs = services.abManager.directories;
- let lowerFilter = filter.toLowerCase();
-
- while (dirs.hasMoreElements()) {
- let addrbook = dirs.getNext().QueryInterface(Ci.nsIAbDirectory);
- let cards = addrbook.childCards;
- while (cards.hasMoreElements()) {
- let card = cards.getNext().QueryInterface(Ci.nsIAbCard);
- //var mail = card.primaryEmail || ""; //XXX
- let displayName = card.displayName;
- if (!displayName)
- displayName = this.generateDisplayName(card.firstName, card.lastName);
-
- if (displayName.toLowerCase().indexOf(lowerFilter) > -1
- || card.primaryEmail.toLowerCase().indexOf(lowerFilter) > -1)
- addresses.push([displayName, card.primaryEmail]);
- }
- }
-
- if (addresses.length < 1) {
- if (!filter)
- dactyl.echoerr(_("addressbook.noContacts"), commandline.FORCE_SINGLELINE);
- else
- dactyl.echoerr(_("addressbook.noMatchingContacts"), filter, commandline.FORCE_SINGLELINE);
- return false;
- }
-
- if (newMail) {
- // Now we have to create a new message
- let args = {};
- args.to = addresses.map(
- address => "\"" + address[0].replace(/"/g, "") + " <" + address[1] + ">\""
- ).join(", ");
-
- mail.composeNewMail(args);
- }
- else {
- let list = template.tabular(["Name", "Address"], [],
- [[util.clip(address[0], 50), address[1]] for ([, address] in Iterator(addresses))]
- );
- commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
- }
- return true;
- }
-}, {
-}, {
- commands: function initCommands() {
- commands.add(["con[tact]"],
- "Add an address book entry",
- function (args) {
- let mailAddr = args[0]; // TODO: support more than one email address
- let firstName = args["-firstname"] || null;
- let lastName = args["-lastname"] || null;
- let displayName = args["-name"] || null;
- if (!displayName)
- displayName = this.generateDisplayName(firstName, lastName);
-
- if (addressbook.add(mailAddr, firstName, lastName, displayName))
- dactyl.echomsg(_("addressbook.added", displayName, mailAddr), 1, commandline.FORCE_SINGLELINE);
- else
- dactyl.echoerr(_("addressbook.cantAdd", mailAddr), commandline.FORCE_SINGLELINE);
-
- },
- {
- argCount: "+",
- options: [{ names: ["-firstname", "-f"], type: CommandOption.STRING, description: "The first name of the contact" },
- { names: ["-lastname", "-l"], type: CommandOption.STRING, description: "The last name of the contact" },
- { names: ["-name", "-n"], type: CommandOption.STRING, description: "The display name of the contact" }]
- });
-
- commands.add(["contacts", "addr[essbook]"],
- "List or open multiple addresses",
- function (args) { addressbook.list(args.string, args.bang); },
- { bang: true });
- },
- mappings: function initMappings() {
- var myModes = config.mailModes;
-
- mappings.add(myModes, ["a"],
- "Open a prompt to save a new addressbook entry for the sender of the selected message",
- function () {
- try {
- var to = gDBView.hdrForFirstSelectedMessage.mime2DecodedAuthor;
- }
- catch (e) {
- dactyl.beep();
- }
-
- if (!to)
- return;
-
- let address = to.substring(to.indexOf("<") + 1, to.indexOf(">"));
-
- let displayName = to.substr(0, to.indexOf("<") - 1);
- if (/^\S+\s+\S+\s*$/.test(displayName)) {
- let names = displayName.split(/\s+/);
- displayName = "-firstname=" + names[0].replace(/"/g, "")
- + " -lastname=" + names[1].replace(/"/g, "");
- }
- else
- displayName = "-name=\"" + displayName.replace(/"/g, "") + "\"";
-
- CommandExMode().open("contact " + address + " " + displayName);
- });
- },
- services: function initServices(dactyl, modules, window) {
- services.add("abManager", "@mozilla.org/abmanager;1", Ci.nsIAbManager);
- }
-});
-
-// vim: set fdm=marker sw=4 sts=4 ts=8 et:
diff --git a/teledactyl/content/compose/compose.js b/teledactyl/content/compose/compose.js
deleted file mode 100644
index 825b59a6..00000000
--- a/teledactyl/content/compose/compose.js
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
-//
-// This work is licensed for reuse under an MIT license. Details are
-// given in the LICENSE.txt file included with this file.
-"use strict";
-
-var Compose = Module("compose", {
- init: function init() {
- var stateListener = {
- QueryInterface: function (id) {
- if (id.equals(Ci.nsIDocumentStateListener))
- return this;
- throw Cr.NS_NOINTERFACE;
- },
-
- // this is (also) fired once the new compose window loaded the message for the first time
- NotifyDocumentStateChanged: function (nowDirty) {
- // only edit with external editor if this window was not cached!
- if (options["autoexternal"] && !window.messageWasEditedExternally/* && !gMsgCompose.recycledWindow*/) {
- window.messageWasEditedExternally = true;
- editor.editFieldExternally();
- }
-
- },
- NotifyDocumentCreated: function () {},
- NotifyDocumentWillBeDestroyed: function () {}
- };
-
- events.listen(window.document, "load", () => {
- if (window.messageWasEditedExternally === undefined) {
- window.messageWasEditedExternally = false;
- GetCurrentEditor().addDocumentStateListener(stateListener);
- }
- }, true);
-
- events.listen(window, "compose-window-close", () => {
- window.messageWasEditedExternally = false;
- }, true);
- }
-}, {
-}, {
- mappings: function initMappings(dactyl, modules, window) {
- mappings.add([modes.COMPOSE],
- ["e"], "Edit message",
- function () { editor.editFieldExternally(); });
-
- mappings.add([modes.COMPOSE],
- ["y"], "Send message now",
- function () { window.goDoCommand("cmd_sendNow"); });
-
- mappings.add([modes.COMPOSE],
- ["Y"], "Send message later",
- function () { window.goDoCommand("cmd_sendLater"); });
-
- // FIXME: does not really work reliably
- mappings.add([modes.COMPOSE],
- ["t"], "Select To: field",
- function () { awSetFocus(0, awGetInputElement(1)); });
-
- mappings.add([modes.COMPOSE],
- ["s"], "Select Subject: field",
- function () { GetMsgSubjectElement().focus(); });
-
- mappings.add([modes.COMPOSE],
- ["i"], "Select message body",
- function () { SetMsgBodyFrameFocus(); });
-
- mappings.add([modes.COMPOSE],
- ["q"], "Close composer, ask when for unsaved changes",
- function () { DoCommandClose(); });
-
- mappings.add([modes.COMPOSE],
- ["Q", "ZQ"], "Force closing composer",
- function () { MsgComposeCloseWindow(true); /* cache window for better performance*/ });
- },
- modes: function initModes(dactyl, modules, window) {
- modes.addMode("COMPOSE", {
- insert: true
- });
- }
-});
-
-// vim: set fdm=marker sw=4 sts=4 ts=8 et:
diff --git a/teledactyl/content/compose/compose.xul b/teledactyl/content/compose/compose.xul
deleted file mode 100644
index b9af4c16..00000000
--- a/teledactyl/content/compose/compose.xul
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- ***** BEGIN LICENSE BLOCK ***** {{{
- Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
-
- This work is licensed for reuse under an MIT license. Details are
- given in the LICENSE.txt file included with this file.
-}}} ***** END LICENSE BLOCK ***** -->
-
-<!--?xml-stylesheet href="chrome://browser/skin/" type="text/css"?-->
-
-<overlay id="teledactyl"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:nc="http://home.netscape.com/NC-rdf#"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-</overlay>
-
-<!-- vim: set fdm=marker sw=4 ts=4 et: -->
diff --git a/teledactyl/content/config.js b/teledactyl/content/config.js
deleted file mode 100644
index 3173eca0..00000000
--- a/teledactyl/content/config.js
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
-//
-// This work is licensed for reuse under an MIT license. Details are
-// given in the LICENSE.txt file included with this file.
-"use strict";
-
-var Config = Module("config", ConfigBase, {
- Local: function Local(dactyl, modules, window)
- let ({ config } = modules, { document } = window) {
- init: function init() {
- init.superapply(this, arguments);
-
- if (!("content" in modules))
- modules.__defineGetter__("content", () => window.content);
-
- util.overlayWindow(window, { append: <><hbox id="statusTextBox" flex=""/></> });
- },
-
- get browser() {
- return let (tabmail = document.getElementById('tabmail'))
- tabmail && tabmail.tabInfo.length ? tabmail.getBrowserForSelectedTab()
- : document.getElementById("messagepane");
- },
-
- tabbrowser: {
- __proto__: Class.makeClosure.call(window.document.getElementById("tabmail")),
- get mTabContainer() { return this.tabContainer; },
- get mTabs() { return this.tabContainer.childNodes; },
- get mCurrentTab() { return this.tabContainer.selectedItem; },
- get mStrip() { return this.tabStrip; },
- get browsers() {
- return [browser for (browser in Iterator(this.mTabs))];
- },
-
- removeTab: function removeTab(tab) this.closeTab(tab),
-
- loadOneTab: function loadOneTab(uri) {
- return this.openTab("contentTab", { contentPage: uri });
- },
- loadURIWithFlags: function loadURIWithFlags() {
- return this.mCurrentTab.loadURIWithFlags.apply(this.mCurrentTab, arguments);
- }
- },
-
- get tabStip() { return this.tabbrowser.tabContainer; },
-
- get mainWidget() {
- return this.isComposeWindow ? document.getElementById("content-frame") : window.GetThreadTree();
- },
-
- get browserModes() { return [modules.modes.MESSAGE]; },
-
- get mailModes() { return [modules.modes.NORMAL]; },
-
- // NOTE: as I don't use TB I have no idea how robust this is. --djk
- get outputHeight() {
- if (!this.isComposeWindow) {
- let container = document.getElementById("tabpanelcontainer").boxObject;
- let deck = document.getElementById("displayDeck");
- let box = document.getElementById("messagepanebox");
- let splitter = document.getElementById("threadpane-splitter").boxObject;
-
- if (splitter.width > splitter.height)
- return container.height - deck.minHeight - box.minHeight- splitter.height;
- else
- return container.height - Math.max(deck.minHeight, box.minHeight);
- }
- else
- return document.getElementById("appcontent").boxObject.height;
- },
-
- removeTab: function removeTab(tab) {
- if (this.tabbrowser.mTabs.length > 1)
- this.tabbrowser.removeTab(tab);
- else
- dactyl.beep();
- },
-
- completers: Class.Memoize(function () {
- return update({ mailfolder: "mailFolder" }, this.__proto__.completers);
- }),
-
- dialogs: {
- about: ["About Thunderbird",
- () => { window.openAboutDialog(); }],
- addons: ["Manage Add-ons",
- () => { window.openAddonsMgr(); }],
- addressbook: ["Address book",
- () => { window.toAddressBook(); }],
- checkupdates: ["Check for updates",
- () => { window.checkForUpdates(); }],
- console: ["JavaScript console",
- () => { window.toJavaScriptConsole(); }],
- dominspector: ["DOM Inspector",
- () => { window.inspectDOMDocument(content.document); }],
- downloads: ["Manage Downloads",
- () => { window.toOpenWindowByType('Download:Manager', 'chrome://mozapps/content/downloads/downloads.xul', 'chrome,dialog=no,resizable'); }],
- preferences: ["Show Thunderbird preferences dialog",
- () => { window.openOptionsDialog(); }],
- printsetup: ["Setup the page size and orientation before printing",
- () => { window.PrintUtils.showPageSetup(); }],
- print: ["Show print dialog",
- () => { window.PrintUtils.print(); }],
- saveframe: ["Save frame to disk",
- () => { window.saveFrameDocument(); }],
- savepage: ["Save page to disk",
- () => { window.saveDocument(window.content.document); }],
- },
-
- focusChange: function focusChange(win) {
- const { modes } = modules;
-
- if (win.top == window)
- return;
-
- // we switch to -- MESSAGE -- mode for Teledactyl when the main HTML widget gets focus
- if (win && win.document instanceof Ci.nsIDOMHTMLDocument
- || dactyl.focusedElement instanceof Ci.nsIDOMHTMLAnchorElement) {
-
- if (this.isComposeWindow)
- modes.set(modes.INSERT, modes.TEXT_EDIT);
- else if (dactyl.mode != modes.MESSAGE)
- modes.main = modes.MESSAGE;
- }
- }
- }
-}, {
-}, {
- commands: function initCommands(dactyl, modules, window) {
- const { commands } = modules;
-
- commands.add(["pref[erences]", "prefs"],
- "Show " + config.host + " preferences",
- function () { window.openOptionsDialog(); },
- { argCount: "0" });
- },
- modes: function initModes(dactyl, modules, window) {
- const { modes } = modules;
-
- this.ignoreKeys = {
- "<Return>": modes.NORMAL | modes.INSERT,
- "<Space>": modes.NORMAL | modes.INSERT,
- "<Up>": modes.NORMAL | modes.INSERT,
- "<Down>": modes.NORMAL | modes.INSERT
- };
- },
- options: function initOptions(dactyl, modules, window) {
- const { options } = modules;
-
- // FIXME: comment obviously incorrect
- // 0: never automatically edit externally
- // 1: automatically edit externally when message window is shown the first time
- // 2: automatically edit externally, once the message text gets focus (not working currently)
- options.add(["autoexternal", "ae"],
- "Edit message with external editor by default",
- "boolean", false);
-
- options.add(["online"],
- "Set the 'work offline' option",
- "boolean", true,
- {
- setter: function (value) {
- if (window.MailOfflineMgr.isOnline() != value)
- window.MailOfflineMgr.toggleOfflineStatus();
- return value;
- },
- getter: function () {
- return window.MailOfflineMgr.isOnline();
- }
- });
- }
-});
-
-// vim: set fdm=marker sw=4 sts=4 ts=8 et:
diff --git a/teledactyl/content/logo.png b/teledactyl/content/logo.png
deleted file mode 100644
index a3934366..00000000
--- a/teledactyl/content/logo.png
+++ /dev/null
Binary files differ
diff --git a/teledactyl/content/mail.js b/teledactyl/content/mail.js
deleted file mode 100644
index 523d6fac..00000000
--- a/teledactyl/content/mail.js
+++ /dev/null
@@ -1,946 +0,0 @@
-// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
-//
-// This work is licensed for reuse under an MIT license. Details are
-// given in the LICENSE.txt file included with this file.
-"use strict";
-
-var Mail = Module("mail", {
- init: function init() {
- // used for asynchronously selecting messages after wrapping folders
- this._selectMessageKeys = [];
- this._selectMessageCount = 1;
- this._selectMessageReverse = false;
-
- this._mailSession = Cc["@mozilla.org/messenger/services/session;1"].getService(Ci.nsIMsgMailSession);
- this._notifyFlags = Ci.nsIFolderListener.intPropertyChanged | Ci.nsIFolderListener.event;
- this._mailSession.AddFolderListener(this._folderListener, this._notifyFlags);
- },
-
- _folderListener: {
- OnItemAdded: function (parentItem, item) {},
- OnItemRemoved: function (parentItem, item) {},
- OnItemPropertyChanged: function (item, property, oldValue, newValue) {},
- OnItemIntPropertyChanged: function (item, property, oldValue, newValue) {},
- OnItemBoolPropertyChanged: function (item, property, oldValue, newValue) {},
- OnItemUnicharPropertyChanged: function (item, property, oldValue, newValue) {},
- OnItemPropertyFlagChanged: function (item, property, oldFlag, newFlag) {},
-
- OnItemEvent: function (folder, event) {
- let eventType = event.toString();
- if (eventType == "FolderLoaded") {
- if (folder) {
- let msgFolder = folder.QueryInterface(Ci.nsIMsgFolder);
- autocommands.trigger("FolderLoaded", { url: msgFolder });
-
- // Jump to a message when requested
- let indices = [];
- if (mail._selectMessageKeys.length > 0) {
- for (let j = 0; j < mail._selectMessageKeys.length; j++)
- indices.push([gDBView.findIndexFromKey(mail._selectMessageKeys[j], true), mail._selectMessageKeys[j]]);
-
- indices.sort();
- let index = mail._selectMessageCount - 1;
- if (mail._selectMessageReverse)
- index = mail._selectMessageKeys.length - 1 - index;
-
- gDBView.selectMsgByKey(indices[index][1]);
- mail._selectMessageKeys = [];
- }
- }
- }
- /*else if (eventType == "ImapHdrDownloaded") {}
- else if (eventType == "DeleteOrMoveMsgCompleted") {}
- else if (eventType == "DeleteOrMoveMsgFailed") {}
- else if (eventType == "AboutToCompact") {}
- else if (eventType == "CompactCompleted") {}
- else if (eventType == "RenameCompleted") {}
- else if (eventType == "JunkStatusChanged") {}*/
- }
- },
-
- _getCurrentFolderIndex: function () {
- // for some reason, the index is interpreted as a string, therefore the parseInt
- return parseInt(gFolderTreeView.getIndexOfFolder(gFolderTreeView.getSelectedFolders()[0]));
- },
-
- _getRSSUrl: function () {
- return gDBView.hdrForFirstSelectedMessage.messageId.replace(/(#.*)?@.*$/, "");
- },
-
- _moveOrCopy: function (copy, destinationFolder, operateOnThread) {
- let folders = mail.getFolders(destinationFolder);
- if (folders.length == 0)
- return void dactyl.echoerr(_("addressbook.noMatchingFolder", destinationFolder));
- else if (folders.length > 1)
- return dactyl.echoerr(_("addressbook.multipleFolderMatches", destinationFolder));
-
- let count = gDBView.selection.count;
- if (!count)
- return void dactyl.beep();
-
- (copy ? MsgCopyMessage : MsgMoveMessage)(folders[0]);
- util.timeout(function () {
- dactyl.echomsg(count + " message(s) " + (copy ? "copied" : "moved") + " to " + folders[0].prettyName, 1);
- }, 100);
- },
-
- _parentIndex: function (index) {
- let parent = index;
- let tree = GetThreadTree();
-
- while (true) {
- let tmp = tree.view.getParentIndex(parent);
- if (tmp >= 0)
- parent = tmp;
- else
- break;
- }
- return parent;
- },
-
- // does not wrap yet, intentional?
- _selectUnreadFolder: function (backwards, count) {
- count = Math.max(1, count);
- let direction = backwards ? -1 : 1;
- let c = this._getCurrentFolderIndex();
- let i = direction;
- let folder;
- while (count > 0 && (c + i) < gFolderTreeView.rowCount && (c + i) >= 0) {
- let resource = gFolderTreeView._rowMap[c + i]._folder;
- if (!resource.isServer && resource.getNumUnread(false)) {
- count -= 1;
- folder = i;
- }
- i += direction;
- }
- if (!folder || count > 0)
- dactyl.beep();
- else
- gFolderTreeView.selection.timedSelect(c + folder, 500);
- },
-
- _escapeRecipient: function (recipient) {
- // strip all ":
- recipient = recipient.replace(/"/g, "");
- return "\"" + recipient + "\"";
- },
-
- get currentAccount() { return this.currentFolder.rootFolder; },
-
- get currentFolder() { return gFolderTreeView.getSelectedFolders()[0]; },
-
- /** @property {[nsISmtpServer]} The list of configured SMTP servers. */
- get smtpServers() {
- let servers = services.smtp.smtpServers;
- let res = [];
-
- while (servers.hasMoreElements()) {
- let server = servers.getNext();
- if (server instanceof Ci.nsISmtpServer)
- res.push(server);
- }
-
- return res;
- },
-
- composeNewMail: function (args) {
- let params = Cc["@mozilla.org/messengercompose/composeparams;1"].createInstance(Ci.nsIMsgComposeParams);
- params.composeFields = Cc["@mozilla.org/messengercompose/composefields;1"].createInstance(Ci.nsIMsgCompFields);
-
- if (args) {
- if (args.originalMsg)
- params.originalMsgURI = args.originalMsg;
- if (args.to)
- params.composeFields.to = args.to;
- if (args.cc)
- params.composeFields.cc = args.cc;
- if (args.bcc)
- params.composeFields.bcc = args.bcc;
- if (args.newsgroups)
- params.composeFields.newsgroups = args.newsgroups;
- if (args.subject)
- params.composeFields.subject = args.subject;
- if (args.body)
- params.composeFields.body = args.body;
-
- if (args.attachments) {
- while (args.attachments.length > 0) {
- let url = args.attachments.pop();
- let file = io.getFile(url);
- if (!file.exists())
- return void dactyl.echoerr(_("mail.cantAttachFile", url), commandline.FORCE_SINGLELINE);
-
- attachment = Cc["@mozilla.org/messengercompose/attachment;1"].createInstance(Ci.nsIMsgAttachment);
- attachment.url = "file://" + file.path;
- params.composeFields.addAttachment(attachment);
- }
- }
- }
-
- params.type = Ci.nsIMsgCompType.New;
-
- services.compose.OpenComposeWindowWithParams(null, params);
- },
-
- // returns an array of nsIMsgFolder objects
- getFolders: function (filter, includeServers, includeMsgFolders) {
- let folders = [];
- if (!filter)
- filter = "";
- else
- filter = filter.toLowerCase();
-
- if (includeServers === undefined)
- includeServers = false;
- if (includeMsgFolders === undefined)
- includeMsgFolders = true;
-
- for (let i = 0; i < gFolderTreeView.rowCount; i++) {
- let resource = gFolderTreeView._rowMap[i]._folder;
- if ((resource.isServer && !includeServers) || (!resource.isServer && !includeMsgFolders))
- continue;
-
- let folderString = resource.server.prettyName + ": " + resource.name;
-
- if (resource.prettiestName.toLowerCase().indexOf(filter) >= 0)
- folders.push(resource);
- else if (folderString.toLowerCase().indexOf(filter) >= 0)
- folders.push(resource);
- }
- return folders;
- },
-
- getNewMessages: function (currentAccountOnly) {
- if (currentAccountOnly)
- MsgGetMessagesForAccount();
- else
- GetMessagesForAllAuthenticatedAccounts();
- },
-
- getStatistics: function (currentAccountOnly) {
- let accounts = currentAccountOnly ? [this.currentAccount]
- : this.getFolders("", true, false);
-
- let unreadCount = 0, totalCount = 0, newCount = 0;
- for (let i = 0; i < accounts.length; i++) {
- let account = accounts[i];
- unreadCount += account.getNumUnread(true); // true == deep (includes subfolders)
- totalCount += account.getTotalMessages(true);
- newCount += account.getNumUnread(true);
- }
-
- return { numUnread: unreadCount, numTotal: totalCount, numNew: newCount };
- },
-
- collapseThread: function () {
- let tree = GetThreadTree();
- if (tree) {
- let parent = this._parentIndex(tree.currentIndex);
- if (tree.changeOpenState(parent, false)) {
- tree.view.selection.select(parent);
- tree.treeBoxObject.ensureRowIsVisible(parent);
- return true;
- }
- }
- return false;
- },
-
- expandThread: function () {
- let tree = GetThreadTree();
- if (tree) {
- let row = tree.currentIndex;
- if (row >= 0 && tree.changeOpenState(row, true))
- return true;
- }
- return false;
- },
-
- /**
- * General-purpose method to find messages.
- *
- * @param {function(nsIMsgDBHdr):boolean} validatorFunc Return
- * true/false whether msg should be selected or not.
- * @param {boolean} canWrap When true, wraps around folders.
- * @param {boolean} openThreads Should we open closed threads?
- * @param {boolean} reverse Change direction of searching.
- */
- selectMessage: function (validatorFunc, canWrap, openThreads, reverse, count) {
- function currentIndex() {
- let index = gDBView.selection.currentIndex;
- if (index < 0)
- index = 0;
- return index;
- }
-
- function closedThread(index) {
- if (!(gDBView.viewFlags & nsMsgViewFlagsType.kThreadedDisplay))
- return false;
-
- index = (typeof index == "number") ? index : currentIndex();
- return !gDBView.isContainerOpen(index) && !gDBView.isContainerEmpty(index);
- }
-
- if (typeof validatorFunc != "function")
- return;
-
- if (typeof count != "number" || count < 1)
- count = 1;
-
- // first try to find in current folder
- if (gDBView) {
- for (let i = currentIndex() + (reverse ? -1 : (openThreads && closedThread() ? 0 : 1));
- reverse ? (i >= 0) : (i < gDBView.rowCount);
- reverse ? i-- : i++) {
- let key = gDBView.getKeyAt(i);
- let msg = gDBView.db.GetMsgHdrForKey(key);
-
- // a closed thread
- if (openThreads && closedThread(i)) {
- let thread = gDBView.db.GetThreadContainingMsgHdr(msg);
- let originalCount = count;
-
- for (let j = (i == currentIndex() && !reverse) ? 1 : (reverse ? thread.numChildren - 1 : 0);
- reverse ? (j >= 0) : (j < thread.numChildren);
- reverse ? j-- : j++) {
- msg = thread.getChildAt(j);
- if (validatorFunc(msg) && --count == 0) {
- // this hack is needed to get the correct message, because getChildAt() does not
- // necessarily return the messages in the order they are displayed
- gDBView.selection.timedSelect(i, GetThreadTree()._selectDelay || 500);
- GetThreadTree().treeBoxObject.ensureRowIsVisible(i);
- if (j > 0) {
- GetThreadTree().changeOpenState(i, true);
- this.selectMessage(validatorFunc, false, false, false, originalCount);
- }
- return;
- }
- }
- }
- else { // simple non-threaded message
- if (validatorFunc(msg) && --count == 0) {
- gDBView.selection.timedSelect(i, GetThreadTree()._selectDelay || 500);
- GetThreadTree().treeBoxObject.ensureRowIsVisible(i);
- return;
- }
- }
- }
- }
-
- // then in other folders
- if (canWrap) {
- this._selectMessageReverse = reverse;
-
- let folders = this.getFolders("", true, true);
- let ci = this._getCurrentFolderIndex();
- for (let i = 1; i < folders.length; i++) {
- let index = (i + ci) % folders.length;
- if (reverse)
- index = folders.length - 1 - index;
-
- let folder = folders[index];
- if (folder.isServer)
- continue;
-
- this._selectMessageCount = count;
- this._selectMessageKeys = [];
-
- // sometimes folder.getMessages can fail with an exception
- // TODO: find out why, and solve the problem
- try {
- var msgs = folder.messages;
- }
- catch (e) {
- msgs = folder.getMessages(msgWindow); // for older thunderbirds
- dactyl.dump("WARNING: " + folder.prettyName + " failed to getMessages, trying old API");
- //continue;
- }
-
- while (msgs.hasMoreElements()) {
- let msg = msgs.getNext().QueryInterface(Ci.nsIMsgDBHdr);
- if (validatorFunc(msg)) {
- count--;
- this._selectMessageKeys.push(msg.messageKey);
- }
- }
-
- if (count <= 0) {
- // SelectFolder is asynchronous, message is selected in this._folderListener
- SelectFolder(folder.URI);
- return;
- }
- }
- }
-
- // TODO: finally for the "rest" of the current folder
-
- dactyl.beep();
- },
-
- setHTML: function (value) {
- let values = [[true, 1, gDisallow_classes_no_html], // plaintext
- [false, 0, 0], // HTML
- [false, 3, gDisallow_classes_no_html]]; // sanitized/simple HTML
-
- if (typeof value != "number" || value < 0 || value > 2)
- value = 1;
-
- gPrefBranch.setBoolPref("mailnews.display.prefer_plaintext", values[value][0]);
- gPrefBranch.setIntPref("mailnews.display.html_as", values[value][1]);
- gPrefBranch.setIntPref("mailnews.display.disallow_mime_handlers", values[value][2]);
- ReloadMessage();
- }
-}, {
-}, {
- commands: function initCommands(dactyl, modules, window) {
- commands.add(["go[to]"],
- "Select a folder",
- function (args) {
- let count = Math.max(0, args.count - 1);
- let arg = args.literalArg || "Inbox";
-
- let folder = mail.getFolders(arg, true, true)[count];
- if (!folder)
- dactyl.echoerr(_("command.goto.folderNotExist", arg));
- else if (dactyl.forceNewTab)
- MsgOpenNewTabForFolder(folder.URI);
- else
- SelectFolder(folder.URI);
- }, {
- argCount: "?",
- completer: function (context) {
- completion.mailFolder(context);
- },
- count: true,
- literal: 0
- });
-
- commands.add(["m[ail]"],
- "Write a new message",
- function (args) {
- let mailargs = {};
- mailargs.to = args.join(", ");
- mailargs.subject = args["-subject"];
- mailargs.bcc = args["-bcc"] || [];
- mailargs.cc = args["-cc"] || [];
- mailargs.body = args["-text"];
- mailargs.attachments = args["-attachment"] || [];
-
- let addresses = args;
- if (mailargs.bcc)
- addresses = addresses.concat(mailargs.bcc);
- if (mailargs.cc)
- addresses = addresses.concat(mailargs.cc);
-
- // TODO: is there a better way to check for validity?
- if (addresses.some(recipient => !(/\S@\S+\.\S/.test(recipient))))
- return void dactyl.echoerr(_("command.mail.invalidEmailAddress"));
-
- mail.composeNewMail(mailargs);
- },
- {
- // TODO: completers, validators - whole shebang. Do people actually use this? --djk
- options: [
- { names: ["-subject", "-s"], type: CommandOption.STRING, description: "Subject line"},
- { names: ["-attachment", "-a"], type: CommandOption.LIST, description: "List of attachments"},
- { names: ["-bcc", "-b"], type: CommandOption.LIST, description: "Blind Carbon Copy addresses"},
- { names: ["-cc", "-c"], type: CommandOption.LIST, description: "Carbon Copy addresses"},
- { names: ["-text", "-t"], type: CommandOption.STRING, description: "Message body"}
- ]
- });
-
- commands.add(["copy[to]"],
- "Copy selected messages",
- function (args) {
- mail._moveOrCopy(true, args.literalArg);
- }, {
- argCount: "1",
- completer: function (context) {
- completion.mailFolder(context);
- },
- literal: 0
- });
-
- commands.add(["move[to]"],
- "Move selected messages",
- function (args) {
- mail._moveOrCopy(false, args.literalArg);
- }, {
- argCount: "1",
- completer: function (context) {
- completion.mailFolder(context);
- },
- literal: 0
- });
-
- commands.add(["empty[trash]"],
- "Empty trash of the current account",
- function () { window.goDoCommand("cmd_emptyTrash"); },
- { argCount: "0" });
-
- commands.add(["get[messages]"],
- "Check for new messages",
- function (args) { mail.getNewMessages(!args.bang); },
- {
- argCount: "0",
- bang: true,
- });
- },
- completion: function initCompletion(dactyl, modules, window) {
- completion.mailFolder = function mailFolder(context) {
- let folders = mail.getFolders(context.filter);
- context.anchored = false;
- context.quote = false;
- context.completions = folders.map(folder =>
- [folder.server.prettyName + ": " + folder.name,
- "Unread: " + folder.getNumUnread(false)]);
- };
- },
- mappings: function initMappings(dactyl, modules, window) {
- var myModes = config.mailModes;
-
- mappings.add(myModes, ["<Return>", "i"],
- "Inspect (focus) message",
- function () { content.focus(); });
-
- mappings.add(myModes, ["I"],
- "Open the message in new tab",
- function () {
- if (gDBView && gDBView.selection.count < 1)
- return void dactyl.beep();
-
- MsgOpenNewTabForMessage();
- });
-
- mappings.add(myModes, ["<Space>"],
- "Scroll message or select next unread one",
- () => Events.PASS);
-
- mappings.add(myModes, ["t"],
- "Select thread",
- function () { gDBView.ExpandAndSelectThreadByIndex(GetThreadTree().currentIndex, false); });
-
- mappings.add(myModes, ["d", "<Del>"],
- "Move mail to Trash folder",
- function () { window.goDoCommand("cmd_delete"); });
-
- mappings.add(myModes, ["j", "<Right>"],
- "Select next message",
- function ({ count }) { mail.selectMessage(msg => true, false, false, false, count); },
- { count: true });
-
- mappings.add(myModes, ["gj"],
- "Select next message, including closed threads",
- function ({ count }) { mail.selectMessage(msg => true, false, true, false, count); },
- { count: true });
-
- mappings.add(myModes, ["J", "<Tab>"],
- "Select next unread message",
- function ({ count }) { mail.selectMessage(msg => !msg.isRead, true, true, false, count); },
- { count: true });
-
- mappings.add(myModes, ["k", "<Left>"],
- "Select previous message",
- function ({ count }) { mail.selectMessage(msg => true, false, false, true, count); },
- { count: true });
-
- mappings.add(myModes, ["gk"],
- "Select previous message",
- function ({ count }) { mail.selectMessage(msg => true, false, true, true, count); },
- { count: true });
-
- mappings.add(myModes, ["K"],
- "Select previous unread message",
- function ({ count }) { mail.selectMessage(msg => !msg.isRead, true, true, true, count); },
- { count: true });
-
- mappings.add(myModes, ["*"],
- "Select next message from the same sender",
- function ({ count }) {
- let author = gDBView.hdrForFirstSelectedMessage.mime2DecodedAuthor.toLowerCase();
- mail.selectMessage(msg => msg.mime2DecodedAuthor.toLowerCase().indexOf(author) == 0, true, true, false, count);
- },
- { count: true });
-
- mappings.add(myModes, ["#"],
- "Select previous message from the same sender",
- function ({ count }) {
- let author = gDBView.hdrForFirstSelectedMessage.mime2DecodedAuthor.toLowerCase();
- mail.selectMessage(msg => msg.mime2DecodedAuthor.toLowerCase().indexOf(author) == 0, true, true, true, count);
- },
- { count: true });
-
- // SENDING MESSAGES
- mappings.add(myModes, ["m"],
- "Compose a new message",
- function () { CommandExMode().open("mail -subject="); });
-
- mappings.add(myModes, ["M"],
- "Compose a new message to the sender of selected mail",
- function () {
- let to = mail._escapeRecipient(gDBView.hdrForFirstSelectedMessage.mime2DecodedAuthor);
- CommandExMode().open("mail " + to + " -subject=");
- });
-
- mappings.add(myModes, ["r"],
- "Reply to sender",
- function () { window.goDoCommand("cmd_reply"); });
-
- mappings.add(myModes, ["R"],
- "Reply to all",
- function () { window.goDoCommand("cmd_replyall"); });
-
- mappings.add(myModes, ["f"],
- "Forward message",
- function () { window.goDoCommand("cmd_forward"); });
-
- mappings.add(myModes, ["F"],
- "Forward message inline",
- function () { window.goDoCommand("cmd_forwardInline"); });
-
- // SCROLLING
- mappings.add(myModes, ["<Down>"],
- "Scroll message down",
- function ({ count }) { buffer.scrollLines(Math.max(count, 1)); },
- { count: true });
-
- mappings.add(myModes, ["<Up>"],
- "Scroll message up",
- function ({ count }) { buffer.scrollLines(-Math.max(count, 1)); },
- { count: true });
-
- mappings.add([modes.MESSAGE], ["<Left>"],
- "Select previous message",
- function ({ count }) { mail.selectMessage(msg => true, false, false, true, count); },
- { count: true });
-
- mappings.add([modes.MESSAGE], ["<Right>"],
- "Select next message",
- function ({ count }) { mail.selectMessage(msg => true, false, false, false, count); },
- { count: true });
-
- // UNDO/REDO
- mappings.add(myModes, ["u"],
- "Undo",
- function () {
- if (messenger.canUndo())
- messenger.undo(msgWindow);
- else
- dactyl.beep();
- });
- mappings.add(myModes, ["<C-r>"],
- "Redo",
- function () {
- if (messenger.canRedo())
- messenger.redo(msgWindow);
- else
- dactyl.beep();
- });
-
- // GETTING MAIL
- mappings.add(myModes, ["gm"],
- "Get new messages",
- function () { mail.getNewMessages(); });
-
- mappings.add(myModes, ["gM"],
- "Get new messages for current account only",
- function () { mail.getNewMessages(true); });
-
- // MOVING MAIL
- mappings.add(myModes, ["c"],
- "Change folders",
- function () { CommandExMode().open("goto "); });
-
- mappings.add(myModes, ["s"],
- "Move selected messages",
- function () { CommandExMode().open("moveto "); });
-
- mappings.add(myModes, ["S"],
- "Copy selected messages",
- function () { CommandExMode().open("copyto "); });
-
- mappings.add(myModes, ["<C-s>"],
- "Archive message",
- function () { mail._moveOrCopy(false, options["archivefolder"]); });
-
- mappings.add(myModes, ["]s"],
- "Select next starred message",
- function ({ count }) { mail.selectMessage(msg => msg.isFlagged, true, true, false, count); },
- { count: true });
-
- mappings.add(myModes, ["[s"],
- "Select previous starred message",
- function ({ count }) { mail.selectMessage(msg => msg.isFlagged, true, true, true, count); },
- { count: true });
-
- mappings.add(myModes, ["]a"],
- "Select next message with an attachment",
- function ({ count }) { mail.selectMessage(msg => gDBView.db.HasAttachments(msg.messageKey), true, true, false, count); },
- { count: true });
-
- mappings.add(myModes, ["[a"],
- "Select previous message with an attachment",
- function ({ count }) { mail.selectMessage(msg => gDBView.db.HasAttachments(msg.messageKey), true, true, true, count); },
- { count: true });
-
- // FOLDER SWITCHING
- mappings.add(myModes, ["gi"],
- "Go to inbox",
- function ({ count }) {
- let folder = mail.getFolders("Inbox", false, true)[(count > 0) ? (count - 1) : 0];
- if (folder)
- SelectFolder(folder.URI);
- else
- dactyl.beep();
- },
- { count: true });
-
- mappings.add(myModes, ["<C-n>"],
- "Select next folder",
- function ({ count }) {
- let newPos = mail._getCurrentFolderIndex() + Math.max(1, count);
- if (newPos >= gFolderTreeView.rowCount) {
- newPos = newPos % gFolderTreeView.rowCount;
- commandline.echo(_("finder.atBottom"), commandline.HL_WARNINGMSG, commandline.APPEND_TO_MESSAGES);
- }
- gFolderTreeView.selection.timedSelect(newPos, 500);
- },
- { count: true });
-
- mappings.add(myModes, ["<C-N>"],
- "Go to next mailbox with unread messages",
- function ({ count }) {
- mail._selectUnreadFolder(false, count);
- },
- { count: true });
-
- mappings.add(myModes, ["<C-p>"],
- "Select previous folder",
- function ({ count }) {
- let newPos = mail._getCurrentFolderIndex() - Math.max(1, count);
- if (newPos < 0) {
- newPos = (newPos % gFolderTreeView.rowCount) + gFolderTreeView.rowCount;
- commandline.echo(_("finder.atTop"), commandline.HL_WARNINGMSG, commandline.APPEND_TO_MESSAGES);
- }
- gFolderTreeView.selection.timedSelect(newPos, 500);
- },
- { count: true });
-
- mappings.add(myModes, ["<C-P>"],
- "Go to previous mailbox with unread messages",
- function ({ count }) {
- mail._selectUnreadFolder(true, count);
- },
- { count: true });
-
- // THREADING
- mappings.add(myModes, ["za"],
- "Toggle thread collapsed/expanded",
- function () { if (!mail.expandThread()) mail.collapseThread(); });
-
- mappings.add(myModes, ["zc"],
- "Collapse thread",
- function () { mail.collapseThread(); });
-
- mappings.add(myModes, ["zo"],
- "Open thread",
- function () { mail.expandThread(); });
-
- mappings.add(myModes, ["zr", "zR"],
- "Expand all threads",
- function () { window.goDoCommand("cmd_expandAllThreads"); });
-
- mappings.add(myModes, ["zm", "zM"],
- "Collapse all threads",
- function () { window.goDoCommand("cmd_collapseAllThreads"); });
-
- mappings.add(myModes, ["<C-i>"],
- "Go forward",
- function ({ count }) { if (count < 1) count = 1; while (count--) GoNextMessage(nsMsgNavigationType.forward, true); },
- { count: true });
-
- mappings.add(myModes, ["<C-o>"],
- "Go back",
- function ({ count }) { if (count < 1) count = 1; while (count--) GoNextMessage(nsMsgNavigationType.back, true); },
- { count: true });
-
- mappings.add(myModes, ["gg"],
- "Select first message",
- function ({ count }) { if (count < 1) count = 1; while (count--) GoNextMessage(nsMsgNavigationType.firstMessage, true); },
- { count: true });
-
- mappings.add(myModes, ["G"],
- "Select last message",
- function ({ count }) { if (count < 1) count = 1; while (count--) GoNextMessage(nsMsgNavigationType.lastMessage, false); },
- { count: true });
-
- // tagging messages
- mappings.add(myModes, ["l"],
- "Label message",
- function ({ arg }) {
- if (!GetSelectedMessages())
- return void dactyl.beep();
-
- switch (arg) {
- case "r": MsgMarkMsgAsRead(); break;
- case "s": MsgMarkAsFlagged(); break;
- case "i": ToggleMessageTagKey(1); break; // Important
- case "w": ToggleMessageTagKey(2); break; // Work
- case "p": ToggleMessageTagKey(3); break; // Personal
- case "t": ToggleMessageTagKey(4); break; // TODO
- case "l": ToggleMessageTagKey(5); break; // Later
- default: dactyl.beep();
- }
- },
- {
- arg: true
- });
-
- // TODO: change binding?
- mappings.add(myModes, ["T"],
- "Mark current folder as read",
- function () {
- if (mail.currentFolder.isServer)
- return dactyl.beep();
-
- mail.currentFolder.markAllMessagesRead(msgWindow);
- });
-
- mappings.add(myModes, ["<C-t>"],
- "Mark all messages as read",
- function () {
- mail.getFolders("", false).forEach(function (folder) { folder.markAllMessagesRead(msgWindow); });
- });
-
- // DISPLAY OPTIONS
- mappings.add(myModes, ["h"],
- "Toggle displayed headers",
- function () {
- let value = gPrefBranch.getIntPref("mail.show_headers", 2);
- gPrefBranch.setIntPref("mail.show_headers", value == 2 ? 1 : 2);
- ReloadMessage();
- });
-
- mappings.add(myModes, ["x"],
- "Toggle HTML message display",
- function () {
- let wantHtml = (gPrefBranch.getIntPref("mailnews.display.html_as", 1) == 1);
- mail.setHTML(wantHtml ? 1 : 0);
- });
-
- // YANKING TEXT
- mappings.add(myModes, ["Y"],
- "Yank subject",
- function () {
- try {
- let subject = gDBView.hdrForFirstSelectedMessage.mime2DecodedSubject;
- dactyl.clipboardWrite(subject, true);
- }
- catch (e) { dactyl.beep(); }
- });
-
- mappings.add(myModes, ["y"],
- "Yank sender or feed URL",
- function () {
- try {
- if (mail.currentAccount.server.type == "rss")
- dactyl.clipboardWrite(mail._getRSSUrl(), true);
- else
- dactyl.clipboardWrite(gDBView.hdrForFirstSelectedMessage.mime2DecodedAuthor, true);
- }
- catch (e) { dactyl.beep(); }
- });
-
- // RSS specific mappings
- mappings.add(myModes, ["p"],
- "Open RSS message in browser",
- function () {
- try {
- if (mail.currentAccount.server.type == "rss")
- messenger.launchExternalURL(mail._getRSSUrl());
- // TODO: what to do for non-rss message?
- }
- catch (e) {
- dactyl.beep();
- }
- });
- },
- services: function initServices(dactyl, modules, window) {
- services.add("smtp", "@mozilla.org/messengercompose/smtp;1", Ci.nsISmtpService);
- services.add("compose", "@mozilla.org/messengercompose;1", "nsIMsgComposeService");
- },
- modes: function initModes(dactyl, modules, window) {
- modes.addMode("MESSAGE", {
- char: "m",
- description: "Active the message is focused",
- bases: [modes.COMMAND]
- });
- },
- options: function initOptions(dactyl, modules, window) {
- // FIXME: why does this default to "Archive", I don't have one? The default
- // value won't validate now. mst please fix. --djk
- options.add(["archivefolder"],
- "Set the archive folder",
- "string", "Archive",
- {
- completer: function (context) {
- completion.mailFolder(context);
- }
- });
-
- // TODO: generate the possible values dynamically from the menu
- options.add(["layout"],
- "Set the layout of the mail window",
- "string", "inherit",
- {
- setter: function (value) {
- switch (value) {
- case "classic": ChangeMailLayout(0); break;
- case "wide": ChangeMailLayout(1); break;
- case "vertical": ChangeMailLayout(2); break;
- // case "inherit" just does nothing
- }
-
- return value;
- },
- completer: function () {
- return [
- ["inherit", "Default View"], // FIXME: correct description?
- ["classic", "Classic View"],
- ["wide", "Wide View"],
- ["vertical", "Vertical View"]
- ];
- }
- });
-
- options.add(["smtpserver", "smtp"],
- "Set the default SMTP server",
- "string", services.smtp.defaultServer.key, // TODO: how should we handle these persistent external defaults - "inherit" or null?
- {
- getter: function () { return services.smtp.defaultServer.key; },
- setter: function (value) {
- let server = mail.smtpServers.filter(s => s.key == value)[0];
- services.smtp.defaultServer = server;
- return value;
- },
- completer: function () {
- return [[s.key, s.serverURI] for ([, s] in Iterator(mail.smtpServers))];
- }
- });
-
- /*options.add(["threads"],
- "Use threading to group messages",
- "boolean", true,
- {
- setter: function (value) {
- if (value)
- MsgSortThreaded();
- else
- MsgSortUnthreaded();
-
- return value;
- }
- });*/
- }
-});
-
-// vim: set fdm=marker sw=4 sts=4 ts=8 et:
diff --git a/teledactyl/defaults/preferences/dactyl.js b/teledactyl/defaults/preferences/dactyl.js
deleted file mode 100644
index bf789242..00000000
--- a/teledactyl/defaults/preferences/dactyl.js
+++ /dev/null
@@ -1,6 +0,0 @@
-pref("extensions.dactyl.name", "teledactyl");
-pref("extensions.dactyl.appName", "Teledactyl");
-pref("extensions.dactyl.idName", "TELEDACTYL");
-pref("extensions.dactyl.fileExt", "tele");
-pref("extensions.dactyl.host", "Thunderbird");
-pref("extensions.dactyl.hostbin", "thunderbird");
diff --git a/teledactyl/install.rdf b/teledactyl/install.rdf
deleted file mode 100644
index bb855ea7..00000000
--- a/teledactyl/install.rdf
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0"?>
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:em="http://www.mozilla.org/2004/em-rdf#">
- <Description about="urn:mozilla:install-manifest"
- em:id="teledactyl@dactyl.googlecode.com"
- em:type="2"
- em:name="Teledactyl"
- em:version="0.6"
- em:description="Thunderbird for Mutt and Vim addicts"
- em:creator="Kris Maglione"
- em:homepageURL="http://5digits.org/teledactyl"
- em:iconURL="chrome://teledactyl/skin/icon.png"
- em:bootstrap="true">
- <em:targetApplication>
- <Description>
- <em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
- <em:minVersion>5.0</em:minVersion>
- <em:maxVersion>8.*</em:maxVersion>
- </Description>
- </em:targetApplication>
- </Description>
-</RDF>
-
-<!-- vim: set fdm=marker sw=4 ts=4 et: -->
diff --git a/teledactyl/locale/en-US/Makefile b/teledactyl/locale/en-US/Makefile
deleted file mode 100644
index 9bb4fb4a..00000000
--- a/teledactyl/locale/en-US/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-NAME = teledactyl
-BASE = ../../../common
-include $(BASE)/Makefile.doc
diff --git a/teledactyl/locale/en-US/all.xml b/teledactyl/locale/en-US/all.xml
deleted file mode 100644
index 59d250a5..00000000
--- a/teledactyl/locale/en-US/all.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/teledactyl/locale/en-US/autocommands.xml b/teledactyl/locale/en-US/autocommands.xml
deleted file mode 100644
index edcaf540..00000000
--- a/teledactyl/locale/en-US/autocommands.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<dl tag="autocommand-list" replace="autocommand-list">
- <dt>ColorScheme</dt> <dd>Triggered after a color scheme has been loaded</dd>
- <dt>DOMLoad</dt> <dd>Triggered when a page's DOM content has fully loaded</dd>
- <dt>DownloadPost</dt> <dd>Triggered when a download has completed</dd>
- <dt>Fullscreen</dt> <dd>Triggered when the browser's fullscreen state changes</dd>
- <dt>LocationChange</dt> <dd>Triggered when changing tabs or when navigating to a new location</dd>
- <dt>PageLoadPre</dt> <dd>Triggered after a page load is initiated</dd>
- <dt>PageLoad</dt> <dd>Triggered when a page gets (re)loaded/opened</dd>
- <dt>ShellCmdPost</dt> <dd>Triggered after executing a shell command with <ex>:!</ex><a>cmd</a></dd>
- <dt>Enter</dt> <dd>Triggered after &dactyl.host; starts</dd>
- <dt>LeavePre</dt> <dd>Triggered before exiting &dactyl.host;, just before destroying each module</dd>
- <dt>Leave</dt> <dd>Triggered before exiting &dactyl.host;</dd>
- <dt>FolderLoad</dt> <dd>Triggered after switching folders in &dactyl.host;</dd>
-</dl>
-
-<dl tag="autocommand-args" replace="autocommand-args">
- <dt>&lt;url></dt> <dd>The URL against which the event was selected.</dd>
- <dt>&lt;title></dt> <dd>The page, bookmark or download title.</dd>
- <dt>&lt;doc></dt> <dd>The document for which the event occurred. Only for <em>DOMLoad</em>, <em>PageLoad</em> and <em>PageLoadPre</em>.</dd>
- <dt>&lt;tab></dt> <dd>The tab in which the event occurred. Only for <em>DOMLoad</em>, <em>PageLoad</em> and <em>PageLoadPre</em>.</dd>
- <dt>&lt;size></dt> <dd>The size of a downloaded file. Only for <em>DownloadPost</em>.</dd>
- <dt>&lt;file></dt> <dd>The target destination of a download. Only for <em>DownloadPost</em>.</dd>
- <dt>&lt;name></dt> <dd>The name of the item. Only for <em>ColorScheme</em> and <em>Sanitize</em>.</dd>
-</dl>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/teledactyl/locale/en-US/intro.xml b/teledactyl/locale/en-US/intro.xml
deleted file mode 100644
index d6145c04..00000000
--- a/teledactyl/locale/en-US/intro.xml
+++ /dev/null
@@ -1,138 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<p replace="intro-text">
- <link topic="&dactyl.apphome;">&dactyl.appName;</link> is a free mailer
- add-on for &dactyl.host;, which combines the best features of the
- <link topic="http://www.mutt.org">Mutt</link> mail client and the
- <link topic="http://www.vim.org">Vim</link> text editor.
-</p>
-
-<!-- TODO: make Teledactyl specific -->
-<ol replace="topics-list">
- <li>
- <link topic="tutorial">Quick-start tutorial</link>:
- A quick-start tutorial for new users.
- </li>
- <li>
- <link topic="starting">Starting &dactyl.appName;</link>:
- How &dactyl.appName; starts up, where it reads the config file, etc.
- </li>
- <li>
- <link topic="browsing">Browsing</link>:
- Basic key mappings and commands needed for a browsing
- session (how to open a web page, go back in history, etc.)
- </li>
- <li>
- <link topic="buffer">Buffer</link>:
- Operations on the current document (scrolling, copying text,
- etc.)
- </li>
- <li>
- <link topic="cmdline">Command Line mode</link>:
- Command-line editing.
- </li>
- <li>
- <link topic="editing">Editing text</link>:
- Text area and input field editing.
- </li>
- <li>
- <link topic="options">Options</link>:
- A description of all options.
- </li>
- <li>
- <link topic="pattern">Text search commands</link>:
- Searching for text in the current buffer.
- </li>
- <li>
- <link topic="tabs">Tabs</link>:
- Managing your tabbed browsing session.
- </li>
- <li>
- <link topic="hints">Hints</link>:
- Selecting hyperlinks and other page elements.
- </li>
- <li>
- <link topic="map">Keyboard shortcuts and commands</link>:
- Defining new key mappings, abbreviations and user commands.
- </li>
- <li>
- <link topic="eval">Expression evaluation</link>:
- Executing JavaScript.
- </li>
- <li>
- <link topic="marks">Marks</link>:
- Using bookmarks, QuickMarks, history and local marks.
- </li>
- <li>
- <link topic="repeat">Repeating commands</link>:
- Using macros to repeat recurring workflows.
- </li>
- <li>
- <link topic="autocommands">Automatic commands</link>:
- Automatically executing code on certain events.
- </li>
- <li>
- <link topic="print">Printing</link>:
- Printing pages.
- </li>
- <li>
- <link topic="gui">&dactyl.appName;'s GUI</link>:
- Accessing &dactyl.host; menus, dialogs and the sidebar.
- </li>
- <li>
- <link topic="styling">Styling the GUI and web pages</link>:
- Changing the styling of content pages and &dactyl.appName; itself.
- </li>
- <li>
- <link topic="message">Error and informational messages</link>:
- A description of informational and error messages.
- </li>
- <li>
- <link topic="developer">Developer information</link>:
- How to write plugins and documentation.
- </li>
- <li>
- <link topic="various">Various commands</link>:
- Other help which doesn't readily fit into any other category.
- </li>
- <li>
- <link topic="plugins">Plugins</link>:
- Documentation for any plugins you have installed.
- </li>
- <li>
- <link topic="index">Index</link>:
- An index of all commands and options.
- </li>
-</ol>
-
-<!-- TODO: make Teledactyl specific -->
-<ul replace="features-list">
- <li>Vim-like keybindings (<k>h</k>, <k>j</k>, <k>gg</k>, <k>ZZ</k>, <k name="C-f"/>, etc.)</li>
- <li>Ex commands (<ex>:quit</ex>, <ex>:open www.foo.com</ex>, …)</li>
- <li>Tab completion for all commands, highly configurable via <o>wildmode</o>, <o>autocomplete</o>, …</li>
- <li>Hit-a-hint like navigation of links (start with <k>f</k> to follow a link)</li>
- <li>Advanced completion of bookmark and history URLs</li>
- <li>Vim-like status line with a Wget-like progress bar</li>
- <li>Minimal GUI (easily hide superfluous menubar and toolbar with <se opt="guioptions"/>)</li>
- <li>Ability to <ex>:source</ex> JavaScript, CSS, and &dactyl.appName; command files</li>
- <li>Easy quick searches (see <ex>:open</ex>)</li>
- <li>Count supported for many commands (<em>3</em><k name="C-o"/> will go back 3 pages)</li>
- <li>Visual bell for errors (<o>visualbell</o>)</li>
- <li>Marks support (<k>m</k><em>a</em> to set mark a, <k>'</k><em>a</em> to jump to it)</li>
- <li><link topic="quickmarks">QuickMark</link> support</li>
- <li><ex>:map</ex>, <ex>:command</ex>, <ex>:normal</ex>, and <t>macros</t></li>
- <li><link topic="i_&lt;C-i>">Editing of text fields</link> with an <link topic="'editor'">external editor</link></li>
- <li>AutoCommands to execute actions on certain events</li>
- <li>A comprehensive help system, explaining all commands, mappings, options, and plugins</li>
-</ul>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/teledactyl/locale/en-US/map.xml b/teledactyl/locale/en-US/map.xml
deleted file mode 100644
index 4038530f..00000000
--- a/teledactyl/locale/en-US/map.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>
-
-<!DOCTYPE overlay SYSTEM "dactyl://content/dtd">
-
-<overlay
- xmlns="&xmlns.dactyl;"
- xmlns:html="&xmlns.html;">
-
-<dl replace=":command-complete-arg-list">
- <dt>abbreviation</dt> <dd>abbreviations</dd>
- <dt>altstyle</dt> <dd>alternate author style sheets</dd>
- <dt>bookmark</dt> <dd>bookmarks</dd>
- <dt>buffer</dt> <dd>buffers</dd>
- <dt>charset</dt> <dd>character sets</dd>
- <dt>color</dt> <dd>color schemes</dd>
- <dt>command</dt> <dd>Ex commands</dd>
- <dt>dialog</dt> <dd>&dactyl.host; dialogs</dd>
- <dt>dir</dt> <dd>directories</dd>
- <dt>environment</dt> <dd>environment variables</dd>
- <dt>event</dt> <dd>autocommand events</dd>
- <dt>extension</dt> <dd>installed extensions</dd>
- <dt>file</dt> <dd>files</dd>
- <dt>help</dt> <dd>help tags</dd>
- <dt>highlight</dt> <dd>highlight groups</dd>
- <dt>history</dt> <dd>browsing history</dd>
- <dt>javascript</dt> <dd>JavaScript expressions</dd>
- <dt>macro</dt> <dd>named macros</dd>
- <dt>mailfolder</dt> <dd>mail folders</dd>
- <dt>mapping</dt> <dd>user mappings</dd>
- <dt>mark</dt> <dd>local page marks</dd>
- <dt>menu</dt> <dd>menu items</dd>
- <dt>option</dt> <dd>&dactyl.appName; options</dd>
- <dt>preference</dt> <dd>&dactyl.host; preferences</dd>
- <dt>qmark</dt> <dd>quick marks</dd>
- <dt>runtime</dt> <dd>runtime paths</dd>
- <dt>search</dt> <dd>search engines and keywords</dd>
- <dt>shellcmd</dt> <dd>shell commands</dd>
- <dt>toolbar</dt> <dd>toolbars</dd>
- <dt>url</dt> <dd>URLs</dd>
- <dt>usercommand</dt> <dd>user commands</dd>
- <dt>custom,<a>thing</a></dt><dd>custom completion, provided by <a>thing</a></dd>
-</dl>
-
-</overlay>
-
-<!-- vim:se sts=4 sw=4 et: -->
diff --git a/teledactyl/locale/en-US/messages.properties b/teledactyl/locale/en-US/messages.properties
deleted file mode 100644
index ddc929b9..00000000
--- a/teledactyl/locale/en-US/messages.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-addressbook.noContacts = No contacts
-addressbook.noMatchingContacts-1 = No contacts matching '%S'
-addressbook.added-2 = Added address: %S <%S>
-addressbook.cantAdd-1 = Could not add contact '%S'
-
-command.goto.folderNotExist-1 = Folder '%S' does not exist
-command.mail.invalidEmailAddress = Invalid e-mail address
-
-mail.noMatchingFolder-1 = No matching folder for %S
-mail.multipleFolderMatches-1 = More than one match for %S
-mail.cantAttachFile = Could not attach file '%S'
-
-# vim:se ft=jproperties tw=0:
-
diff --git a/teledactyl/skin/icon.png b/teledactyl/skin/icon.png
deleted file mode 100644
index d07edc6d..00000000
--- a/teledactyl/skin/icon.png
+++ /dev/null
Binary files differ