// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2010 by anekos <anekos@snca.net>
-// Copyright (c) 2010-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2010-2012 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
/** @scope modules */
+/**
+ * A user-defined input mode binding of a typed string to an automatically
+ * inserted expansion string.
+ *
+ * Abbreviations have a left-hand side (LHS) whose text is replaced by that of
+ * the right-hand side (RHS) when triggered by an Input mode expansion key.
+ * E.g. an abbreviation with a LHS of "gop" and RHS of "Grand Old Party" will
+ * replace the former with the latter.
+ *
+ * @param {[Mode]} modes The modes in which this abbreviation is active.
+ * @param {string} lhs The left hand side of the abbreviation; the text to
+ * be replaced.
+ * @param {string|function(nsIEditor):string} rhs The right hand side of
+ * the abbreviation; the replacement text. This may either be a string
+ * literal or a function that will be passed the appropriate nsIEditor.
+ * @private
+ */
var Abbreviation = Class("Abbreviation", {
init: function (modes, lhs, rhs) {
this.modes = modes.sort();
this.rhs = rhs;
},
+ /**
+ * Returns true if this abbreviation's LHS and RHS are equal to those in
+ * *other*.
+ *
+ * @param {Abbreviation} other The abbreviation to test.
+ * @returns {boolean} The result of the comparison.
+ */
equals: function (other) this.lhs == other.lhs && this.rhs == other.rhs,
+ /**
+ * Returns the abbreviation's expansion text.
+ *
+ * @param {nsIEditor} editor The editor in which abbreviation expansion is
+ * occurring.
+ * @returns {string}
+ */
expand: function (editor) String(callable(this.rhs) ? this.rhs(editor) : this.rhs),
+ /**
+ * Returns true if this abbreviation is defined for all *modes*.
+ *
+ * @param {[Mode]} modes The modes to test.
+ * @returns {boolean} The result of the comparison.
+ */
modesEqual: function (modes) array.equals(this.modes, modes),
+ /**
+ * Returns true if this abbreviation is defined for *mode*.
+ *
+ * @param {Mode} mode The mode to test.
+ * @returns {boolean} The result of the comparison.
+ */
inMode: function (mode) this.modes.some(function (_mode) _mode == mode),
+ /**
+ * Returns true if this abbreviation is defined in any of *modes*.
+ *
+ * @param {[Modes]} modes The modes to test.
+ * @returns {boolean} The result of the comparison.
+ */
inModes: function (modes) modes.some(function (mode) this.inMode(mode), this),
+ /**
+ * Remove *mode* from the list of supported modes for this abbreviation.
+ *
+ * @param {Mode} mode The mode to remove.
+ */
removeMode: function (mode) {
this.modes = this.modes.filter(function (m) m != mode).sort();
},
+ /**
+ * @property {string} The mode display characters associated with the
+ * supported mode combination.
+ */
get modeChar() Abbreviation.modeChar(this.modes)
}, {
modeChar: function (_modes) {
this._store = {};
},
+ /** @property {boolean} True if there are no abbreviations. */
get empty() !values(this._store).nth(util.identity, 0),
/**
*
* @param {Mode} mode The mode of the abbreviation.
* @param {string} lhs The LHS of the abbreviation.
+ * @returns {Abbreviation} The matching abbreviation.
*/
get: function (mode, lhs) {
let abbrevs = this._store[mode];
- return abbrevs && set.has(abbrevs, lhs) ? abbrevs[lhs] : null;
+ return abbrevs && Set.has(abbrevs, lhs) ? abbrevs[lhs] : null;
},
/**
- * @property {Abbreviation[]} The list of the abbreviations merged from
+ * @property {[Abbreviation]} The list of the abbreviations merged from
* each mode.
*/
get merged() {
nonkeyword: /[ "']/
};
- this._match = util.regexp(<><![CDATA[
+ this._match = util.regexp(literal(/*
(^ | \s | <nonkeyword>) (<keyword>+ )$ | // full-id
(^ | \s | <keyword> ) (<nonkeyword>+ <keyword>)$ | // end-id
(^ | \s ) (\S* <nonkeyword> )$ // non-id
- ]]></>, "x", params);
- this._check = util.regexp(<><![CDATA[
+ */), "x", params);
+ this._check = util.regexp(literal(/*
^ (?:
<keyword>+ | // full-id
<nonkeyword>+ <keyword> | // end-id
\S* <nonkeyword> // non-id
) $
- ]]></>, "x", params);
+ */), "x", params);
},
get: deprecated("group.abbrevs.get", { get: function get() this.user.closure.get }),
},
/**
- * Lists all abbreviations matching *modes* and *lhs*.
+ * Lists all abbreviations matching *modes*, *lhs* and optionally *hives*.
*
* @param {Array} modes List of modes.
* @param {string} lhs The LHS of the abbreviation.
+ * @param {[Hive]} hives List of hives.
+ * @optional
*/
- list: function (modes, lhs) {
- let hives = contexts.allGroups.abbrevs.filter(function (h) !h.empty);
+ list: function (modes, lhs, hives) {
+ let hives = hives || contexts.allGroups.abbrevs.filter(function (h) !h.empty);
function abbrevs(hive)
hive.merged.filter(function (abbr) (abbr.inModes(modes) && abbr.lhs.indexOf(lhs) == 0));
- let list = <table>
- <tr highlight="Title">
- <td/>
- <td style="padding-right: 1em;">Mode</td>
- <td style="padding-right: 1em;">Abbrev</td>
- <td style="padding-right: 1em;">Replacement</td>
- </tr>
- <col style="min-width: 6em; padding-right: 1em;"/>
- {
- template.map(hives, function (hive) let (i = 0)
- <tr style="height: .5ex;"/> +
- template.map(abbrevs(hive), function (abbrev)
- <tr>
- <td highlight="Title">{!i++ ? hive.name : ""}</td>
- <td>{abbrev.modeChar}</td>
- <td>{abbrev.lhs}</td>
- <td>{abbrev.rhs}</td>
- </tr>) +
- <tr style="height: .5ex;"/>)
- }
- </table>;
-
- // TODO: Move this to an ItemList to show this automatically
- if (list.*.length() === list.text().length() + 2)
- dactyl.echomsg(_("abbrev.none"));
- else
- commandline.commandOutput(list);
+ let list = ["table", {},
+ ["tr", { highlight: "Title" },
+ ["td"],
+ ["td", { style: "padding-right: 1em;" }, _("title.Mode")],
+ ["td", { style: "padding-right: 1em;" }, _("title.Abbrev")],
+ ["td", { style: "padding-right: 1em;" }, _("title.Replacement")]],
+ ["col", { style: "min-width: 6em; padding-right: 1em;" }],
+ hives.map(function (hive) let (i = 0) [
+ ["tr", { style: "height: .5ex;" }],
+ abbrevs(hive).map(function (abbrev)
+ ["tr", {},
+ ["td", { highlight: "Title" }, !i++ ? String(hive.name) : ""],
+ ["td", {}, abbrev.modeChar],
+ ["td", {}, abbrev.lhs],
+ ["td", {}, abbrev.rhs]]),
+ ["tr", { style: "height: .5ex;" }]])];
+
+ // FIXME?
+ // // TODO: Move this to an ItemList to show this automatically
+ // if (list.*.length() === list.text().length() + 2)
+ // dactyl.echomsg(_("abbreviation.none"));
+ // else
+ commandline.commandOutput(list);
}
}, {
user: contexts.hives.abbrevs.user
});
},
- completion: function () {
+ completion: function initCompletion() {
completion.abbreviation = function abbreviation(context, modes, group) {
group = group || abbreviations.user;
let fn = modes ? function (abbr) abbr.inModes(modes) : util.identity;
context.completions = group.merged.filter(fn);
};
},
-
- commands: function () {
+ commands: function initCommands() {
function addAbbreviationCommands(modes, ch, modeDescription) {
modes.sort();
modeDescription = modeDescription ? " in " + modeDescription + " mode" : "";
dactyl.assert(!args.length || abbreviations._check.test(lhs),
_("error.invalidArgument"));
- if (!rhs)
- abbreviations.list(modes, lhs || "");
+ if (!rhs) {
+ let hives = args.explicitOpts["-group"] ? [args["-group"]] : null;
+ abbreviations.list(modes, lhs || "", hives);
+ }
else {
if (args["-javascript"])
rhs = contexts.bindMacro({ literalArg: rhs }, "-javascript", ["editor"]);
args["-group"].add(modes, lhs, rhs);
}
}, {
+ identifier: "abbreviate",
completer: function (context, args) {
if (args.length == 1)
return completion.abbreviation(context, modes, args["-group"]);
command: this.name,
arguments: [abbr.lhs],
literalArg: abbr.rhs,
- options: callable(abbr.rhs) ? {"-javascript": null} : {}
+ options: {
+ "-javascript": callable(abbr.rhs) ? null : undefined
+ }
}
for ([, abbr] in Iterator(abbreviations.user.merged))
if (abbr.modesEqual(modes))
if (args.bang)
args["-group"].clear(modes);
else if (!args["-group"].remove(modes, args[0]))
- return dactyl.echoerr(_("abbrev.noSuch"));
+ return dactyl.echoerr(_("abbreviation.noSuch"));
}, {
argCount: "?",
bang: true,
}
addAbbreviationCommands([modes.INSERT, modes.COMMAND_LINE], "", "");
- addAbbreviationCommands([modes.INSERT], "i", "insert");
- addAbbreviationCommands([modes.COMMAND_LINE], "c", "command line");
+ [modes.INSERT, modes.COMMAND_LINE].forEach(function (mode) {
+ addAbbreviationCommands([mode], mode.char, mode.displayName);
+ });
}
});
-// vim: set fdm=marker sw=4 ts=4 et:
+// vim: set fdm=marker sw=4 sts=4 ts=8 et: