]> git.donarmstrong.com Git - dactyl.git/blob - common/content/quickmarks.js
Import 1.0b7.1 supporting Firefox up to 8.*
[dactyl.git] / common / content / quickmarks.js
1 // Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
2 // Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
3 // Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
4 //
5 // This work is licensed for reuse under an MIT license. Details are
6 // given in the LICENSE.txt file included with this file.
7 "use strict";
8
9 /** @scope modules */
10
11 /**
12 * @instance quickmarks
13 */
14 var QuickMarks = Module("quickmarks", {
15     init: function () {
16         this._qmarks = storage.newMap("quickmarks", { store: true });
17         storage.addObserver("quickmarks", function () {
18             statusline.updateStatus();
19         }, window);
20     },
21
22     /**
23      * Adds a new quickmark with name *qmark* referencing the URL *location*.
24      * Any existing quickmark with the same name will be replaced.
25      *
26      * @param {string} qmark The name of the quickmark {A-Z}.
27      * @param {string} location The URL accessed by this quickmark.
28      */
29     add: function add(qmark, location) {
30         this._qmarks.set(qmark, location);
31         dactyl.echomsg({ domains: [util.getHost(location)], message: _("quickmark.added", qmark, location) }, 1);
32     },
33
34     /**
35      * Returns a list of QuickMarks associates with the given URL.
36      *
37      * @param {string} url The url to find QuickMarks for.
38      * @returns {[string]}
39      */
40     find: function find(url) {
41         let res = [];
42         for (let [k, v] in this._qmarks)
43             if (dactyl.parseURLs(v).some(function (u) String.replace(u, /#.*/, "") == url))
44                 res.push(k);
45         return res;
46     },
47
48     /**
49      * Returns the URL of the given QuickMark, or null if none exists.
50      *
51      * @param {string} mark The mark to find.
52      * @returns {string} The mark's URL.
53      */
54     get: function (mark) this._qmarks.get(mark) || null,
55
56     /**
57      * Deletes the specified quickmarks. The *filter* is a list of quickmarks
58      * and ranges are supported. Eg. "ab c d e-k".
59      *
60      * @param {string} filter The list of quickmarks to delete.
61      *
62      */
63     remove: function remove(filter) {
64         let pattern = util.charListToRegexp(filter, "a-zA-Z0-9");
65
66         for (let [qmark, ] in this._qmarks) {
67             if (pattern.test(qmark))
68                 this._qmarks.remove(qmark);
69         }
70     },
71
72     /**
73      * Removes all quickmarks.
74      */
75     removeAll: function removeAll() {
76         this._qmarks.clear();
77     },
78
79     /**
80      * Opens the URL referenced by the specified *qmark*.
81      *
82      * @param {string} qmark The quickmark to open.
83      * @param {object} where A set of parameters specifying how to open the
84      *     URL. See {@link Dactyl#open}.
85      */
86     jumpTo: function jumpTo(qmark, where) {
87         let url = this.get(qmark);
88
89         if (url)
90             dactyl.open(url, where);
91         else
92             dactyl.echoerr(_("quickmark.notSet"));
93     },
94
95     /**
96      * Lists all quickmarks matching *filter* in the message window.
97      *
98      * @param {string} filter The list of quickmarks to display, e.g. "a-c i O-X".
99      */
100     list: function list(filter) {
101         let marks = [k for ([k, v] in this._qmarks)];
102         let lowercaseMarks = marks.filter(function (x) /[a-z]/.test(x)).sort();
103         let uppercaseMarks = marks.filter(function (x) /[A-Z]/.test(x)).sort();
104         let numberMarks    = marks.filter(function (x) /[0-9]/.test(x)).sort();
105
106         marks = Array.concat(lowercaseMarks, uppercaseMarks, numberMarks);
107
108         dactyl.assert(marks.length > 0, _("quickmark.none"));
109
110         if (filter.length > 0) {
111             let pattern = util.charListToRegexp(filter, "a-zA-Z0-9");
112             marks = marks.filter(function (qmark) pattern.test(qmark));
113             dactyl.assert(marks.length >= 0, _("quickmark.noMatching", filter.quote()));
114         }
115
116         commandline.commandOutput(template.tabular(["QuickMark", "URL"], [],
117             ([mark, quickmarks._qmarks.get(mark)] for ([k, mark] in Iterator(marks)))));
118     }
119 }, {
120 }, {
121     commands: function () {
122         commands.add(["delqm[arks]"],
123             "Delete the specified QuickMarks",
124             function (args) {
125                 // TODO: finish arg parsing - we really need a proper way to do this. :)
126                 // assert(args.bang ^ args[0])
127                 dactyl.assert( args.bang ||  args[0], _("error.argumentRequired"));
128                 dactyl.assert(!args.bang || !args[0], _("error.invalidArgument"));
129
130                 if (args.bang)
131                     quickmarks.removeAll();
132                 else
133                     quickmarks.remove(args[0]);
134             },
135             {
136                 argCount: "?",
137                 bang: true,
138                 completer: function (context) completion.quickmark(context)
139             });
140
141         commands.add(["qma[rk]"],
142             "Mark a URL with a letter for quick access",
143             function (args) {
144                 dactyl.assert(/^[a-zA-Z0-9]$/.test(args[0]),
145                               _("quickmark.invalid"));
146                 if (!args[1])
147                     quickmarks.add(args[0], buffer.uri.spec);
148                 else
149                     quickmarks.add(args[0], args[1]);
150             },
151             {
152                 argCount: "+",
153                 completer: function (context, args) {
154                     if (args.length == 1)
155                         return completion.quickmark(context);
156                     if (args.length == 2) {
157                         context.fork("current", 0, this, function (context) {
158                             context.title = ["Extra Completions"];
159                             context.completions = [
160                                 [quickmarks.get(args[0]), _("option.currentValue")]
161                             ].filter(function ([k, v]) k);
162                         });
163                         context.fork("url", 0, completion, "url");
164                     }
165                 },
166                 literal: 1
167             });
168
169         commands.add(["qmarks"],
170             "Show the specified QuickMarks",
171             function (args) {
172                 quickmarks.list(args[0] || "");
173             }, {
174                 argCount: "?",
175                 completer: function (context) completion.quickmark(context),
176             });
177     },
178     completion: function () {
179         completion.quickmark = function (context) {
180             context.title = ["QuickMark", "URL"];
181             context.generate = function () Iterator(quickmarks._qmarks);
182         };
183     },
184     mappings: function () {
185         var myModes = config.browserModes;
186
187         mappings.add(myModes,
188             ["go"], "Jump to a QuickMark",
189             function ({ arg }) { quickmarks.jumpTo(arg, dactyl.CURRENT_TAB); },
190             { arg: true });
191
192         mappings.add(myModes,
193             ["gn"], "Jump to a QuickMark in a new tab",
194             function ({ arg }) { quickmarks.jumpTo(arg, { from: "quickmark", where: dactyl.NEW_TAB }); },
195             { arg: true });
196
197         mappings.add(myModes,
198             ["M"], "Add new QuickMark for current URL",
199             function ({ arg }) {
200                 dactyl.assert(/^[a-zA-Z0-9]$/.test(arg), _("quickmark.invalid"));
201                 quickmarks.add(arg, buffer.uri.spec);
202             },
203             { arg: true });
204     }
205 });
206
207 // vim: set fdm=marker sw=4 ts=4 et: