diff --git a/common/content/commands.js b/common/content/commands.js index 8bd700d7..f79584c7 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -335,12 +335,13 @@ const Command = Class("Command", { case "-keys": let silent = args["-silent"]; rhs = events.canonicalKeys(rhs, true); - var action = function action(count) - events.feedkeys(commands.replaceTokens(rhs, { count: count }), - noremap, silent); + let macro = util.compileMacro(rhs, true); + var action = function action(count) events.feedkeys(macro({ count: count }), + noremap, silent); break; case "-ex": - action = function action() commands.execute(rhs, makeParams.apply(this, arguments), + macro = util.compileMacro(rhs, true); + action = function action() commands.execute(macro, makeParams.apply(this, arguments), false, null, action.sourcing); action.sourcing = io.sourcing && update({}, io.sourcing); break; @@ -572,8 +573,10 @@ const Commands = Module("commands", { args = update({}, args || {}); - if (tokens) - string = commands.replaceTokens(string, tokens); + if (tokens && !callable(string)) + string = util.compileMacro(string, true); + if (callable(string)) + string = string(tokens || {}); let lines = string.split(/\r\n|[\r\n]/); @@ -1150,34 +1153,6 @@ const Commands = Module("commands", { this._exCommands = this._exCommands.filter(function (c) c !== cmd); for (let name in values(cmd.names)) delete this._exMap[name]; - }, - - // FIXME: still belong here? Also used for autocommand parameters. - /** - * Returns a string with all tokens in *string* matching "" replaced - * with "value". Where "key" is a property of the specified *tokens* object - * and "value" is the corresponding value. The token can be used to - * include a literal "<" in the returned string. Any tokens prefixed with - * "q-" will be quoted except for which is treated like . - * - * @param {string} str The string with tokens to replace. - * @param {Object} tokens A map object whose keys are replaced with its - * values. - * @returns {string} - */ - replaceTokens: function replaceTokens(str, tokens) { - return str.replace(/<((?:q-)?)([a-zA-Z]+)?>/g, function (match, quote, token) { - if (token == "lt") // Don't quote, as in Vim (but, why so in Vim? You'd think people wouldn't say if they didn't want it) - return "<"; - let res = tokens[token]; - if (res === undefined) // Ignore anything undefined - res = "<" + token + ">"; - if (res === null) - res = ""; - if (quote && typeof res != "number") - return Commands.quoteArg['"'](res); - return res; - }); } }, { // returns [count, parsed_argument] diff --git a/common/content/io.js b/common/content/io.js index dc5eae04..7b009baa 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -586,7 +586,7 @@ lookup: file.append(config.name + ".vim"); dactyl.assert(!file.exists() || args.bang, "File exists"); - let template = @@ -631,7 +631,7 @@ execute 'syn match Option "\<\%(no\|inv\)\=\%(' . \ join(s:toggleOptions, '\|') . \ '\)\>!\=" contained nextgroup=SetMod' -syn match SetMod "\%(\<[a-z_]\+\)\@<=&" contained +syn match SetMod "\%(\[a-z_]\+\)\@<=&" contained syn region JavaScript start="\%(^\s*\%(javascript\|js\)\s\+\)\@<=" end="$" contains=@javascriptTop keepend oneline syn region JavaScript matchgroup=JavaScriptDelimiter @@ -642,7 +642,7 @@ execute 'syn region Css start="' . s:cssRegionStart . '" end="$" contains= execute 'syn region Css matchgroup=CssDelimiter' \ 'start="' . s:cssRegionStart . '<<\s*\z(\h\w*\)"hs=s+2 end="^\z1$" contains=@cssTop fold' -syn match Notation "<[0-9A-Za-z-]\+>" +syn match Notation "[0-9A-Za-z-]\+>" syn match Comment +".*$+ contains=Todo,@Spell syn keyword Todo FIXME NOTE TODO XXX contained @@ -671,7 +671,7 @@ let &cpo = s:cpo_save unlet s:cpo_save " vim: tw=130 et ts=4 sw=4: -]]>; +]]>), true); const WIDTH = 80; function wrap(prefix, items, sep) { @@ -693,7 +693,7 @@ unlet s:cpo_save return lines.map(function (l) l.join("")).join("\n").replace(/\s+\n/gm, "\n"); } - file.write(commands.replaceTokens(String(template), { + file.write(template({ name: config.name, autocommands: wrap("syn keyword " + config.name + "AutoEvent ", keys(config.autocommands)), diff --git a/common/modules/util.jsm b/common/modules/util.jsm index bb023335..3d9f7c61 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -256,10 +256,14 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) return stack.top; }, - compileMacro: function compileFormat(macro) { + compileMacro: function compileFormat(macro, keepUnknown) { let stack = [frame()]; stack.__defineGetter__("top", function () this[this.length - 1]); + let unknown = util.identity; + if (!keepUnknown) + unknown = function () ""; + function frame() update( function _frame(obj) _frame === stack.top || _frame.valid(obj) ? @@ -274,15 +278,15 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) let match, end = 0; let re = util.regexp( | // 3 - (\]>) // 4 + (< (.*?) >) | // 3 4 + (\]>) // 5 ) ]]>, "gy"); while (match = re.exec(macro)) { - let [, prefix, open, macro, close] = match; + let [, prefix, open, full, macro, close] = match; end += match[0].length; if (prefix) @@ -302,14 +306,14 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) let quote = util.identity; if (flags.q) - quote = function quote(obj) typeof obj === "number" ? obj : Commands.quote(obj); + quote = function quote(obj) typeof obj === "number" ? obj : String.quote(obj); if (set.has(defaults, name)) stack.top.elements.push(quote(defaults[name])); else { stack.top.elements.push(update( - function (obj) obj[name] != null ? quote(obj[name]) : "", - { test: function (obj) obj[name] != null })); + function (obj) obj[name] != null ? quote(obj[name]) : unknown(full), + { test: function (obj) obj[name] != null && obj[name] !== false })); for (let elem in array.iterValues(stack)) elem.seen[name] = true;