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>
5 // This work is licensed for reuse under an MIT license. Details are
6 // given in the LICENSE.txt file included with this file.
12 * @instance quickmarks
14 var QuickMarks = Module("quickmarks", {
16 this._qmarks = storage.newMap("quickmarks", { store: true });
17 storage.addObserver("quickmarks", function () {
18 statusline.updateStatus();
23 * Adds a new quickmark with name *qmark* referencing the URL *location*.
24 * Any existing quickmark with the same name will be replaced.
26 * @param {string} qmark The name of the quickmark {A-Z}.
27 * @param {string} location The URL accessed by this quickmark.
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);
35 * Returns a list of QuickMarks associates with the given URL.
37 * @param {string} url The url to find QuickMarks for.
40 find: function find(url) {
42 for (let [k, v] in this._qmarks)
43 if (dactyl.parseURLs(v).some(function (u) String.replace(u, /#.*/, "") == url))
49 * Returns the URL of the given QuickMark, or null if none exists.
51 * @param {string} mark The mark to find.
52 * @returns {string} The mark's URL.
54 get: function (mark) this._qmarks.get(mark) || null,
57 * Deletes the specified quickmarks. The *filter* is a list of quickmarks
58 * and ranges are supported. Eg. "ab c d e-k".
60 * @param {string} filter The list of quickmarks to delete.
63 remove: function remove(filter) {
64 let pattern = util.charListToRegexp(filter, "a-zA-Z0-9");
66 for (let [qmark, ] in this._qmarks) {
67 if (pattern.test(qmark))
68 this._qmarks.remove(qmark);
73 * Removes all quickmarks.
75 removeAll: function removeAll() {
80 * Opens the URL referenced by the specified *qmark*.
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}.
86 jumpTo: function jumpTo(qmark, where) {
87 let url = this.get(qmark);
90 dactyl.open(url, where);
92 dactyl.echoerr(_("quickmark.notSet"));
96 * Lists all quickmarks matching *filter* in the message window.
98 * @param {string} filter The list of quickmarks to display, e.g. "a-c i O-X".
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();
106 marks = Array.concat(lowercaseMarks, uppercaseMarks, numberMarks);
108 dactyl.assert(marks.length > 0, _("quickmark.none"));
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()));
116 commandline.commandOutput(template.tabular(["QuickMark", "URL"], [],
117 ([mark, quickmarks._qmarks.get(mark)] for ([k, mark] in Iterator(marks)))));
121 commands: function () {
122 commands.add(["delqm[arks]"],
123 "Delete the specified QuickMarks",
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"));
131 quickmarks.removeAll();
133 quickmarks.remove(args[0]);
138 completer: function (context) completion.quickmark(context)
141 commands.add(["qma[rk]"],
142 "Mark a URL with a letter for quick access",
144 dactyl.assert(/^[a-zA-Z0-9]$/.test(args[0]),
145 _("quickmark.invalid"));
147 quickmarks.add(args[0], buffer.uri.spec);
149 quickmarks.add(args[0], args[1]);
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]), "Current Value"]
161 ].filter(function ([k, v]) k);
163 context.fork("url", 0, completion, "url");
169 commands.add(["qmarks"],
170 "Show the specified QuickMarks",
172 quickmarks.list(args[0] || "");
175 completer: function (context) completion.quickmark(context),
178 completion: function () {
179 completion.quickmark = function (context) {
180 context.title = ["QuickMark", "URL"];
181 context.generate = function () Iterator(quickmarks._qmarks);
184 mappings: function () {
185 var myModes = config.browserModes;
187 mappings.add(myModes,
188 ["go"], "Jump to a QuickMark",
189 function ({ arg }) { quickmarks.jumpTo(arg, dactyl.CURRENT_TAB); },
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 }); },
197 mappings.add(myModes,
198 ["M"], "Add new QuickMark for current URL",
200 dactyl.assert(/^[a-zA-Z0-9]$/.test(arg), _("quickmark.invalid"));
201 quickmarks.add(arg, buffer.uri.spec);
207 // vim: set fdm=marker sw=4 ts=4 et: