diff --git a/common/content/abbreviations.js b/common/content/abbreviations.js
new file mode 100644
index 00000000..d41ccaff
--- /dev/null
+++ b/common/content/abbreviations.js
@@ -0,0 +1,300 @@
+// Copyright (c) 2006-2009 by Martin Stubenschrott
+// Copyright (c) 2010 by anekos
+// Copyright (c) 2010 by Kris Maglion
+//
+// This work is licensed for reuse under an MIT license. Details are
+// given in the License.txt file included with this file.
+
+
+/** @scope modules */
+
+const Abbreviation = Class("Abbreviation", {
+ init: function (modes, lhs, rhs) {
+ this.modes = modes.sort();
+ this.lhs = lhs;
+ this.rhs = rhs;
+ },
+
+ equals: function (other) {
+ return this.lhs == other.lhs && this.rhs == other.rhs;
+ },
+
+ expand: function (editor) String(callable(this.rhs) ? this.rhs(editor) : this.rhs),
+
+ modesEqual: function (modes) array.equals(this.modes, modes),
+
+ inMode: function (mode) this.modes.some(function (_mode) _mode == mode),
+
+ inModes: function (modes) modes.some(function (mode) this.inMode(mode), this),
+
+ removeMode: function (mode) {
+ this.modes = this.modes.filter(function (m) m != mode).sort();
+ },
+
+ get modeChar() Abbreviation.modeChar(this.modes)
+}, {
+ modeChar: function (_modes) {
+ let result = "";
+ for ([, mode] in Iterator(_modes))
+ result += modes.getMode(mode).char;
+ if (/^(ic|ci)$/(result))
+ result = "!";
+ return result;
+ }
+});
+
+const Abbreviations = Module("abbreviations", {
+ init: function () {
+ this.abbrevs = {};
+
+ // (summarized from Vim's ":help abbreviations")
+ //
+ // There are three types of abbreviations.
+ //
+ // full-id: Consists entirely of keyword characters.
+ // ("foo", "g3", "-1")
+ //
+ // end-id: Ends in a keyword character, but all other
+ // are not keyword characters.
+ // ("#i", "..f", "$/7")
+ //
+ // non-id: Ends in a non-keyword character, but the
+ // others can be of any type other than space
+ // and tab.
+ // ("def#", "4/7$")
+ //
+ // Example strings that cannot be abbreviations:
+ // "a.b", "#def", "a b", "_$r"
+ //
+ // For now, a keyword character is anything except for \s, ", or '
+ // (i.e., whitespace and quotes). In Vim, a keyword character is
+ // specified by the 'iskeyword' setting and is a much less inclusive
+ // list.
+ //
+ // TODO: Make keyword definition closer to Vim's default keyword
+ // definition (which differs across platforms).
+
+ let nonkw = "\\s\"'";
+ let keyword = "[^" + nonkw + "]";
+ let nonkeyword = "[" + nonkw + "]";
+
+ let fullId = keyword + "+";
+ let endId = nonkeyword + "+" + keyword;
+ let nonId = "\\S*" + nonkeyword;
+
+ // Used in add and expand
+ this._match = fullId + "|" + endId + "|" + nonId;
+ },
+
+ /**
+ * Adds a new abbreviation.
+ *
+ * @param {Abbreviation}
+ */
+ add: function (abbr) {
+ if (!(abbr instanceof Abbreviation))
+ abbr = Abbreviation.apply(null, arguments);
+
+ for (let [, mode] in Iterator(abbr.modes)) {
+ if (!this.abbrevs[mode])
+ this.abbrevs[mode] = {};
+ this.abbrevs[mode][abbr.lhs] = abbr;
+ }
+ },
+
+ /**
+ * Returns matched abbreviation.
+ *
+ * @param {mode}
+ * @param {string}
+ */
+ get: function (mode, lhs) {
+ let abbrevs = this.abbrevs[mode];
+ return abbrevs && abbrevs[lhs];
+ },
+
+ /**
+ * Returns the abbreviation that matches the given text.
+ *
+ * @returns {Abbreviation}
+ */
+ match: function (mode, text) {
+ let match = text.match(RegExp('(' + abbreviations._match + ')$'));
+ if (match)
+ return abbreviations.get(mode, match[0]);
+ return null;
+ },
+
+ /**
+ * The list of the abbreviations merged from each modes.
+ */
+ get merged() {
+ let result = [];
+ let lhses = [];
+ let modes = [mode for (mode in this.abbrevs)];
+
+ for (let [, mabbrevs] in Iterator(this.abbrevs))
+ lhses = lhses.concat([key for (key in mabbrevs)]);
+ lhses.sort();
+ lhses = util.Array.uniq(lhses);
+
+ for (let [, lhs] in Iterator(lhses)) {
+ let exists = {};
+ for (let [, mabbrevs] in Iterator(this.abbrevs)) {
+ let abbr = mabbrevs[lhs];
+ if (abbr && !exists[abbr.rhs]) {
+ exists[abbr.rhs] = 1;
+ result.push(abbr);
+ }
+ }
+ }
+
+ return result;
+ },
+
+ /**
+ * Lists all abbreviations matching modes and lhs.
+ *
+ * @param {Array} list of mode.
+ * @param {string} lhs The LHS of the abbreviation.
+ */
+ list: function (modes, lhs) {
+ let list = this.merged.filter(function (abbr) (abbr.inModes(modes) && abbr.lhs.indexOf(lhs) == 0));
+
+ if (!list.length)
+ dactyl.echomsg("No abbreviations found");
+ else if (list.length == 1) {
+ let head = list[0];
+ dactyl.echo(head.modeChar + " " + head.lhs + " " + head.rhs, commandline.FORCE_SINGLELINE); // 2 spaces, 3 spaces
+ }
+ else {
+ list = list.map(function (abbr) [abbr.modeChar, abbr.lhs, abbr.rhs]);
+ list = template.tabular(["", "LHS", "RHS"], [], list);
+ commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
+ }
+ },
+
+ /**
+ * Remove the specified abbreviations.
+ *
+ * @param {Array} list of mode.
+ * @param {string} lhs of abbreviation.
+ * @returns {boolean} did the deleted abbreviation exist?
+ */
+ remove: function (modes, lhs) {
+ let result = false;
+ for (let [, mode] in Iterator(modes)) {
+ if ((mode in this.abbrevs) && (lhs in this.abbrevs[mode])) {
+ result = true;
+ this.abbrevs[mode][lhs].removeMode(mode);
+ delete this.abbrevs[mode][lhs];
+ }
+ }
+ return result;
+ },
+
+ /**
+ * Removes all abbreviations specified modes.
+ *
+ * @param {Array} list of mode.
+ */
+ removeAll: function (modes) {
+ for (let [, mode] in modes) {
+ if (!(mode in this.abbrevs))
+ return;
+ for (let [, abbr] in this.abbrevs[mode])
+ abbr.removeMode(mode);
+ delete this.abbrevs[mode];
+ }
+ }
+}, {
+}, {
+ completion: function () {
+ // TODO: shouldn't all of these have a standard signature (context, args, ...)? --djk
+ completion.abbreviation = function abbreviation(context, args, modes) {
+ if (args.completeArg == 0) {
+ let abbrevs = abbreviations.merged.filter(function (abbr) abbr.inModes(modes));
+ context.completions = [[abbr.lhs, abbr.rhs] for ([, abbr] in Iterator(abbrevs))];
+ }
+ };
+ },
+
+ commands: function () {
+ function addAbbreviationCommands(modes, ch, modeDescription) {
+ modes.sort();
+ modeDescription = modeDescription ? " in " + modeDescription + " mode" : "";
+
+ // Why? --Kris
+ function splitAbbrev(abbrev) abbrev.match(RegExp("^(\\s*)($|" + abbreviations._match + ")(?:\\s*$|(\\s+)(.*))")) || [];
+
+ commands.add([ch ? ch + "a[bbrev]" : "ab[breviate]"],
+ "Abbreviate a key sequence" + modeDescription,
+ function (args) {
+ let [,, lhs,, rhs] = splitAbbrev(args[0]);
+ dactyl.assert(lhs, "E474: Invalid argument");
+
+ if (rhs) {
+ if (args["-javascript"]) {
+ let expr = rhs;
+ rhs = dactyl.userfunc("editor", expr);
+ rhs.toString = function () expr;
+ }
+ abbreviations.add(modes, lhs, rhs);
+ }
+ else {
+ abbreviations.list(modes, lhs || "");
+ }
+ }, {
+ options: [
+ {
+ names: ["-javascript", "-js", "-j"],
+ description: "Expand this abbreviation by evaluating its right-hand-side as JavaScript"
+ }
+ ],
+ completer: function (context, args) {
+ let [, sp1, lhs, sp2, rhs] = splitAbbrev(args[0]);
+ if (rhs == null)
+ return completion.abbreviation(context, args, modes)
+ context.advance((sp1 + lhs + sp2).length);
+ if (args["-javascript"])
+ return completion.javascript(context);
+ },
+ literal: 0,
+ serial: function () [ {
+ command: this.name,
+ arguments: [abbr.lhs],
+ literalArg: abbr.rhs,
+ options: callable(abbr.rhs) ? {"-javascript": null} : {}
+ }
+ for ([, abbr] in Iterator(abbreviations.merged))
+ if (abbr.modesEqual(modes))
+ ]
+ });
+
+ commands.add([ch ? ch + "una[bbrev]" : "una[bbreviate]"],
+ "Remove an abbreviation" + modeDescription,
+ function (args) {
+ let lhs = args.literalArg;
+ if (!lhs)
+ return dactyl.echoerr("E474: Invalid argument");
+ if (!abbreviations.remove(modes, lhs))
+ return dactyl.echoerr("E24: No such abbreviation");
+ }, {
+ argCount: "1",
+ completer: function (context, args) completion.abbreviation(context, args, modes),
+ literal: 0
+ });
+
+ commands.add([ch + "abc[lear]"],
+ "Remove all abbreviations" + modeDescription,
+ function () { abbreviations.removeAll(modes); },
+ { argCount: "0" });
+ }
+
+ addAbbreviationCommands([modes.INSERT, modes.COMMAND_LINE], "", "");
+ addAbbreviationCommands([modes.INSERT], "i", "insert");
+ addAbbreviationCommands([modes.COMMAND_LINE], "c", "command line");
+ }
+});
+
+// vim: set fdm=marker sw=4 ts=4 et:
diff --git a/common/content/commandline.js b/common/content/commandline.js
index c5391df3..686d0590 100644
--- a/common/content/commandline.js
+++ b/common/content/commandline.js
@@ -1487,13 +1487,13 @@ const CommandLine = Module("commandline", {
["", '"', "'"], "Expand command line abbreviation",
function () {
commandline.resetCompletions();
- return editor.expandAbbreviation("c");
+ return editor.expandAbbreviation(modes.COMMAND_LINE);
},
{ route: true });
mappings.add(myModes,
["", ""], "Expand command line abbreviation",
- function () { editor.expandAbbreviation("c"); });
+ function () { editor.expandAbbreviation(modes.COMMAND_LINE); });
mappings.add([modes.NORMAL],
["g<"], "Redisplay the last command output",
diff --git a/common/content/dactyl-overlay.js b/common/content/dactyl-overlay.js
index 219da375..c9e966f8 100644
--- a/common/content/dactyl-overlay.js
+++ b/common/content/dactyl-overlay.js
@@ -42,6 +42,7 @@
"modules",
"storage",
"util",
+ "abbreviations",
"autocommands",
"buffer",
"commandline",
diff --git a/common/content/editor.js b/common/content/editor.js
index e43c8bfc..23c3470f 100644
--- a/common/content/editor.js
+++ b/common/content/editor.js
@@ -16,56 +16,6 @@ const Editor = Module("editor", {
//
this._lastFindChar = null;
this._lastFindCharFunc = null;
- // XXX: this strikes me as a rather odd ds; everyone's a critic --djk
- this._abbreviations = {}; // this._abbreviations["lhr"][0]["{i,c,!}","rhs"]
-
- // (summarized from Vim's ":help this._abbreviations")
- //
- // There are three types of this._abbreviations:
- //
- // full-id: Consists entirely of keyword characters.
- // ("foo", "g3", "-1")
- //
- // end-id: Ends in a keyword character, but all other
- // are not keyword characters.
- // ("#i", "..f", "$/7")
- //
- // non-id: Ends in a non-keyword character, but the
- // others can be of any type other than space
- // and tab.
- // ("def#", "4/7$")
- //
- // Example strings that cannot be this._abbreviations:
- // "a.b", "#def", "a b", "_$r"
- //
- // For now, a keyword character is anything except for \s, ", or '
- // (i.e., whitespace and quotes). In Vim, a keyword character is
- // specified by the 'iskeyword' setting and is a much less inclusive
- // list.
- //
- // TODO: Make keyword definition closer to Vim's default keyword
- // definition (which differs across platforms).
- //
-
- let nonkw = "\\s\"'";
- let keyword = "[^" + nonkw + "]";
- let nonkeyword = "[" + nonkw + "]";
-
- let fullId = keyword + "+";
- let endId = nonkeyword + "+" + keyword;
- let nonId = "\\S*" + nonkeyword;
-
- // Used in addAbbrevation and expandAbbreviation
- this._abbrevmatch = fullId + "|" + endId + "|" + nonId;
-
- },
-
- // For the record, some of this code I've just finished throwing
- // away makes me want to pull someone else's hair out. --Kris
- abbrevs: function () {
- for (let [lhs, abbr] in Iterator(this._abbreviations))
- for (let [, rhs] in Iterator(abbr))
- yield [lhs, rhs];
},
line: function () {
@@ -416,225 +366,31 @@ const Editor = Module("editor", {
return;
},
- // Abbreviations {{{
-
- // NOTE: I think this comment block is trying to say something but no
- // one is listening. In space, no one can hear you scream. --djk
- //
- // System for adding this._abbreviations:
- //
- // filter == ! delete all, and set first (END)
- //
- // if filter == ! remove all and add it as only END
- //
- // variant 1: rhs matches anywhere in loop
- //
- // 1 mod matches anywhere in loop
- // a) simple replace and
- // I) (maybe there's another rhs that matches? not possible)
- // (when there's another item, it's opposite mod with different rhs)
- // (so do nothing further but END)
- //
- // 2 mod does not match
- // a) the opposite is there -> make a ! and put it as only and END
- // (b) a ! is there. do nothing END)
- //
- // variant 2: rhs matches *no*were in loop and filter is c or i
- // every kind of current combo is possible to 1 {c,i,!} or two {c and i}
- //
- // 1 mod is ! split into two i + c END
- // 1 not !: opposite mode (first), add/change 'second' and END
- // 1 not !: same mode (first), overwrite first this END
- //
- // TODO: I don't like these funky filters, I am a funky filter hater. --djk
- // : make this a separate object
- // : use Struct for individual this._abbreviations
- // : rename "filter" arg "mode"
- /**
- * Adds a new abbreviation. Abbreviations consist of a LHS (the text
- * that is replaced when the abbreviation is expanded) and a RHS (the
- * replacement text).
- *
- * @param {string} filter The mode filter. This specifies the modes in
- * which this abbreviation is available. Either:
- * "c" - applies in command-line mode
- * "i" - applies in insert mode
- * "!" - applies in both command-line and insert modes
- * @param {string} lhs The LHS of the abbreviation.
- * @param {string} rhs The RHS of the abbreviation.
- */
- addAbbreviation: function (filter, lhs, rhs) {
- if (!this._abbreviations[lhs]) {
- this._abbreviations[lhs] = [];
- this._abbreviations[lhs][0] = [filter, rhs];
- return;
- }
-
- if (filter == "!") {
- if (this._abbreviations[lhs][1])
- this._abbreviations[lhs][1] = "";
- this._abbreviations[lhs][0] = [filter, rhs];
- return;
- }
-
- for (let i = 0; i < this._abbreviations[lhs].length; i++) {
- if (this._abbreviations[lhs][i][1] == rhs) {
- if (this._abbreviations[lhs][i][0] == filter) {
- this._abbreviations[lhs][i] = [filter, rhs];
- return;
- }
- else {
- if (this._abbreviations[lhs][i][0] != "!") {
- if (this._abbreviations[lhs][1])
- this._abbreviations[lhs][1] = "";
- this._abbreviations[lhs][0] = ["!", rhs];
- return;
- }
- else
- return;
- }
- }
- }
-
- if (this._abbreviations[lhs][0][0] == "!") {
- let tmpOpp = ("i" == filter) ? "c" : "i";
- this._abbreviations[lhs][1] = [tmpOpp, this._abbreviations[lhs][0][1]];
- this._abbreviations[lhs][0] = [filter, rhs];
- return;
- }
-
- if (this._abbreviations[lhs][0][0] != filter)
- this._abbreviations[lhs][1] = [filter, rhs];
- else
- this._abbreviations[lhs][0] = [filter, rhs];
- },
-
/**
* Expands an abbreviation in the currently active textbox.
*
- * @param {string} filter The mode filter.
+ * @param {string} mode The mode filter.
* @see #addAbbreviation
*/
- expandAbbreviation: function (filter) {
+ expandAbbreviation: function (mode) {
let textbox = Editor.getEditor();
if (!textbox)
return false;
let text = textbox.value;
let currStart = textbox.selectionStart;
let currEnd = textbox.selectionEnd;
- let foundWord = text.substring(0, currStart).replace(RegExp("^(.|\\n)*?\\s*(" + this._abbrevmatch + ")$", "m"), "$2"); // get last word \b word boundary
- if (!foundWord)
- return true;
-
- for (let lhs in this._abbreviations) {
- for (let i = 0; i < this._abbreviations[lhs].length; i++) {
- if (lhs == foundWord && (this._abbreviations[lhs][i][0] == filter || this._abbreviations[lhs][i][0] == "!")) {
- // if found, replace accordingly
- let len = foundWord.length;
- let abbrText = this._abbreviations[lhs][i][1];
- text = text.substring(0, currStart - len) + abbrText + text.substring(currStart);
- textbox.value = text;
- textbox.selectionStart = currStart - len + abbrText.length;
- textbox.selectionEnd = currEnd - len + abbrText.length;
- break;
- }
- }
+ let abbrev = abbreviations.match(mode, text.substring(0, currStart).replace(/.*\s/g, ""));
+ if (abbrev) {
+ let len = abbrev.lhs.length;
+ let abbrText = abbrev.expand(textbox);
+ text = text.substring(0, currStart - len) + abbrText + text.substring(currStart);
+ textbox.value = text;
+ textbox.selectionStart = currStart - len + abbrText.length;
+ textbox.selectionEnd = currEnd - len + abbrText.length;
}
+
return true;
},
-
- /**
- * Returns all abbreviations matching filter and lhs.
- *
- * @param {string} filter The mode filter.
- * @param {string} lhs The LHS of the abbreviation.
- * @returns {Array} The matching abbreviations [mode, lhs, rhs]
- * @see #addAbbreviation
- */
- getAbbreviations: function (filter, lhs) {
- // ! -> list all, on c or i ! matches too
- let searchFilter = (filter == "!") ? "!ci" : filter + "!";
- return [[mode, left, right] for ([left, [mode, right]] in this.abbrevs())
- if (searchFilter.indexOf(mode) >= 0 && left.indexOf(lhs || "") == 0)];
- },
-
- /**
- * Lists all abbreviations matching filter and lhs.
- *
- * @param {string} filter The mode filter.
- * @param {string} lhs The LHS of the abbreviation.
- * @see #addAbbreviation
- */
- listAbbreviations: function (filter, lhs) {
- let list = this.getAbbreviations(filter, lhs);
-
- if (!list.length)
- dactyl.echomsg("No abbreviations found");
- else if (list.length == 1) {
- let [mode, lhs, rhs] = list[0];
-
- dactyl.echo(mode + " " + lhs + " " + rhs, commandline.FORCE_SINGLELINE); // 2 spaces, 3 spaces
- }
- else
- commandline.commandOutput(template.tabular(["", "LHS", "RHS"], [], list));
- },
-
- /**
- * Deletes all abbreviations matching filter and lhs.
- *
- * @param {string} filter The mode filter.
- * @param {string} lhs The LHS of the abbreviation.
- * @see #addAbbreviation
- */
- removeAbbreviation: function (filter, lhs) {
- if (!lhs) {
- dactyl.echoerr("E474: Invalid argument");
- return false;
- }
-
- if (this._abbreviations[lhs]) { // this._abbreviations exists
- if (filter == "!") {
- this._abbreviations[lhs] = "";
- return true;
- }
- else {
- if (!this._abbreviations[lhs][1]) { // only one exists
- if (this._abbreviations[lhs][0][0] == "!") { // exists as ! -> no 'full' delete
- this._abbreviations[lhs][0][0] = (filter == "i") ? "c" : "i"; // ! - i = c; ! - c = i
- return true;
- }
- else if (this._abbreviations[lhs][0][0] == filter) {
- this._abbreviations[lhs] = "";
- return true;
- }
- }
- else { // two this._abbreviations exist ( 'i' or 'c' (filter as well))
- if (this._abbreviations[lhs][0][0] == "c" && filter == "c")
- this._abbreviations[lhs][0] = this._abbreviations[lhs][1];
-
- this._abbreviations[lhs][1] = "";
-
- return true;
- }
- }
- }
-
- dactyl.echoerr("E24: No such abbreviation");
- return false;
- },
-
- /**
- * Removes all abbreviations matching filter.
- *
- * @param {string} filter The mode filter.
- * @see #addAbbreviation
- */
- removeAllAbbreviations: function (filter) {
- let searchFilter = (filter == "!") ? "!ci" : filter + "!";
- for (let [lhs, [mode, rhs]] in this.abbrevs())
- if (searchFilter.indexOf(mode) >= 0)
- this.removeAbbreviation(filter, lhs);
- }
}, {
getEditor: function () dactyl.focus,
@@ -646,67 +402,6 @@ const Editor = Module("editor", {
return ed.controllers.getControllerForCommand("cmd_beginLine");
}
}, {
- commands: function () {
- // mode = "i" -> add :iabbrev, :iabclear and :iunabbrev commands
- function addAbbreviationCommands(ch, modeDescription) {
- let mode = ch || "!";
- modeDescription = modeDescription ? " in " + modeDescription + " mode" : "";
-
- commands.add([ch ? ch + "a[bbrev]" : "ab[breviate]"],
- "Abbreviate a key sequence" + modeDescription,
- function (args) {
- let matches = args.string.match(RegExp("^\\s*($|" + editor._abbrevmatch + ")(?:\\s*$|\\s+(.*))"));
- dactyl.assert(matches, "E474: Invalid argument");
-
- let [, lhs, rhs] = matches;
- if (rhs)
- editor.addAbbreviation(mode, lhs, rhs);
- else
- editor.listAbbreviations(mode, lhs || "");
- }, {
- completer: function (context, args) completion.abbreviation(context, args, mode),
- literal: 0,
- serialize: function () [ {
- command: this.name,
- arguments: [lhs],
- literalArg: abbr[1]
- }
- for ([lhs, abbr] in editor.abbrevs())
- if (abbr[0] == mode)
- ]
- });
-
- commands.add([ch ? ch + "una[bbrev]" : "una[bbreviate]"],
- "Remove an abbreviation" + modeDescription,
- function (args) { editor.removeAbbreviation(mode, args.literalArg); }, {
- argCount: "1",
- completer: function (context, args) completion.abbreviation(context, args, mode),
- literal: 0
- });
-
- commands.add([ch + "abc[lear]"],
- "Remove all this._abbreviations" + modeDescription,
- function () { editor.removeAllAbbreviations(mode); },
- { argCount: "0" });
- }
-
- addAbbreviationCommands("", "");
- addAbbreviationCommands("i", "insert");
- addAbbreviationCommands("c", "command line");
- },
-
- completion: function () {
- // TODO: shouldn't all of these have a standard signature (context, args, ...)? --djk
- completion.abbreviation = function abbreviation(context, args, mode) {
- mode = mode || "!";
-
- if (args.completeArg == 0) {
- let abbreviations = editor.getAbbreviations(mode);
- context.completions = [[lhs, ""] for ([, [, lhs,]] in Iterator(abbreviations))];
- }
- };
- },
-
mappings: function () {
var myModes = [modes.INSERT, modes.COMMAND_LINE];
@@ -866,16 +561,16 @@ const Editor = Module("editor", {
mappings.add([modes.INSERT],
["", ""], "Expand insert mode abbreviation",
- function () { editor.expandAbbreviation("i"); },
+ function () { editor.expandAbbreviation(modes.INSERT); },
{ route: true });
mappings.add([modes.INSERT],
[""], "Expand insert mode abbreviation",
- function () { editor.expandAbbreviation("i"); document.commandDispatcher.advanceFocus(); });
+ function () { editor.expandAbbreviation(modes.INSERT); document.commandDispatcher.advanceFocus(); });
mappings.add([modes.INSERT],
["", ""], "Expand insert mode abbreviation",
- function () { editor.expandAbbreviation("i"); });
+ function () { editor.expandAbbreviation(modes.INSERT); });
// textarea mode
mappings.add([modes.TEXTAREA],
diff --git a/common/locale/en-US/map.xml b/common/locale/en-US/map.xml
index 13754b8b..4f859089 100644
--- a/common/locale/en-US/map.xml
+++ b/common/locale/en-US/map.xml
@@ -416,6 +416,17 @@
lhs. If no arguments are given, list all
abbreviations.
+
+
+ If the -javascript (short names -js,
+ -j) option is given, lhs is expanded to
+ the value returned by the JavaScript code
+ rhs. The code is evaluated with the variable
+ editor set to the editable element that the
+ abbreviation is currently being expanded in. The code
+ should not make any changes to the contents of
+ the editor.
+
diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS
index 6ccbdbab..4cf5f3bf 100644
--- a/pentadactyl/NEWS
+++ b/pentadactyl/NEWS
@@ -28,6 +28,7 @@
* Added ‘transliterated’ option to 'hintmatching'
* Added 'autocomplete' option for specifying which completion
contexts should be autocompleted
+ * Added -javascript option to :abbrev and :map
* Added several new options to :map
* Removed the :source line at the end of files generated by
:mkpentadactylrc