1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-21 23:47:58 +01:00

Replace %format strings with our standard <macro> format strings in 'editor' and the like.

--HG--
extra : rebase_source : b5a658dd9f07e30f7e9cb589bb6efca8fd260a66
This commit is contained in:
Kris Maglione
2010-12-18 09:32:09 -05:00
parent 3d6406751b
commit 3f343d0d98
4 changed files with 104 additions and 13 deletions

View File

@@ -961,7 +961,7 @@ const Buffer = Module("buffer", {
let doc = buffer.focusedFrame.document; let doc = buffer.focusedFrame.document;
if (isArray(url)) { if (isArray(url)) {
if (options.get("editor").has("l")) if (options.get("editor").has("line"))
this.viewSourceExternally(url[0] || doc, url[1]); this.viewSourceExternally(url[0] || doc, url[1]);
else else
window.openDialog("chrome://global/content/viewSource.xul", window.openDialog("chrome://global/content/viewSource.xul",

View File

@@ -242,7 +242,7 @@ const Editor = Module("editor", {
}, },
editFileExternally: function (path, line, column) { editFileExternally: function (path, line, column) {
let args = options.get("editor").format({ f: path, l: line, c: column }); let args = options.get("editor").format({ file: path, line: line, column: column });
dactyl.assert(args.length >= 1, "No editor specified"); dactyl.assert(args.length >= 1, "No editor specified");
@@ -772,19 +772,19 @@ const Editor = Module("editor", {
options: function () { options: function () {
options.add(["editor"], options.add(["editor"],
"The external text editor", "The external text editor",
"string", "gvim -f +%l %f", { "string", "gvim -f +<line> <file>", {
format: function (obj, value) { format: function (obj, value) {
let args = commands.parseArgs(value || this.value, { argCount: "*", allowUnknownOptions: true }) let args = commands.parseArgs(value || this.value, { argCount: "*", allowUnknownOptions: true })
.map(util.compileFormat).filter(function (fmt) fmt.valid(obj)) .map(util.compileMacro).filter(function (fmt) fmt.valid(obj))
.map(function (fmt) fmt(obj)); .map(function (fmt) fmt(obj));
if (obj["f"] && !this.has("f")) if (obj["file"] && !this.has("file"))
args.push(obj["f"]); args.push(obj["file"]);
return args; return args;
}, },
has: function (key) set.has(util.compileFormat(this.value).seen, key), has: function (key) set.has(util.compileMacro(this.value).seen, key),
validator: function (value) { validator: function (value) {
this.format({}, value); this.format({}, value);
return Object.keys(util.compileFormat(value).seen).every(function (k) "cfl".indexOf(k) >= 0) return Object.keys(util.compileMacro(value).seen).every(function (k) ["column", "file", "line"].indexOf(k) >= 0)
} }
}); });

View File

@@ -88,6 +88,30 @@
<str>line: 32 'Lieder eines fahrenden Gesellen.txt'</str> <str>line: 32 'Lieder eines fahrenden Gesellen.txt'</str>
</p> </p>
<p tag="macro-string">
Some options may be given format strings containing macro replacements in
the form of <em>&lt;<a>name</a>></em>. These tokens are replaced by
the parameter <a>name</a> as specified in the relevant documentation.
If the token is in the form <em>&lt;q-<a>name</a>></em>, the value of the
parameter is automatically <link topic="quoting">quoted</link>.
</p>
<p>
Any substring enclosed by <em>&lt;[</em>
and <em>]></em> is automatically elided if any of the contained macros
characters aren't currently valid. A literal <em>&lt;</em> or <em>></em>
character may be included with the special escape sequences <em>&lt;lt></em>
or <em>&lt;gt></em> respectively.
</p>
<p>
For example, given the format string
<str><em>&lt;[</em>(cmd: <em>&lt;column></em>) <em>]>&lt;[</em>line: <em>&lt;line> ]>&lt;file></em></str>,
where <em>line</em>=<hl key="Number">32</hl> and
<em>file</em>=<str delim="'">Lieder eines fahrenden Gesellen.txt</str>,
the result is formatted as
<str>line: 32 'Lieder eines fahrenden Gesellen.txt'</str>
</p>
<h2 tag="set-option E764">Setting options</h2> <h2 tag="set-option E764">Setting options</h2>
<item> <item>
@@ -553,7 +577,7 @@
<tags>'editor'</tags> <tags>'editor'</tags>
<spec>'editor'</spec> <spec>'editor'</spec>
<type>string</type> <type>string</type>
<default>gvim -f</default> <default><![CDATA[gvim -f +<line> <file>]]></default>
<description> <description>
<p> <p>
Set the external text editor. Set the external text editor.
@@ -562,16 +586,16 @@
</p> </p>
<p> <p>
Accepts a <t>format-string</t> with the following escapes available. Accepts a <t>macro-string</t> with the following escapes available.
Arguments containing escapes which are not relevant to a given call Arguments containing escapes which are not relevant to a given call
are automatically elided. All field splitting is done before format are automatically elided. All field splitting is done before format
characters are processed. characters are processed.
</p> </p>
<dl> <dl>
<dt>%f</dt> <dd>The file to edit. Appended as the final argument if missing.</dd> <dt>&lt;file></dt> <dd>The file to edit. Appended as the final argument if missing.</dd>
<dt>%l</dt> <dd>The line number at which to position the cursor.</dd> <dt>&lt;line></dt> <dd>The line number at which to position the cursor.</dd>
<dt>%c</dt> <dd>The column at which to position the cursor.</dd> <dt>&lt;column></dt> <dd>The column at which to position the cursor.</dd>
</dl> </dl>
<warning> <warning>

View File

@@ -244,6 +244,73 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
return stack.top; return stack.top;
}, },
compileMacro: function compileFormat(macro) {
let stack = [frame()];
stack.__defineGetter__("top", function () this[this.length - 1]);
function frame() update(
function _frame(obj)
_frame === stack.top || _frame.valid(obj) ?
_frame.elements.map(function (e) callable(e) ? e(obj) : e).join("") : "",
{
elements: [],
seen: {},
valid: function (obj) this.elements.every(function (e) !e.test || e.test(obj))
});
let defaults = { lt: "<", gt: ">" };
let match, end = 0;
let re = util.regexp(<![CDATA[
(.*?) // 1
(?:
(<\[) | // 2
< (.*?) > | // 3
(\]>) // 4
)
]]>, "gy");
while (match = re.exec(macro)) {
let [, prefix, open, macro, close] = match;
end += match[0].length;
if (prefix)
stack.top.elements.push(prefix);
if (open) {
let f = frame();
stack.top.elements.push(f);
stack.push(f);
}
else if (close) {
stack.pop();
util.assert(stack.length, "Unmatched %] in macro");
}
else {
let [, flags, name] = /^((?:[a-z]-)*)(.*)/.exec(macro);
flags = set(flags);
let quote = util.identity;
if (flags.q)
quote = function quote(obj) typeof obj === "number" ? obj : Commands.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 }));
for (let elem in array.iterValues(stack))
elem.seen[name] = true;
}
}
}
if (end < macro.length)
stack.top.elements.push(macro.substr(end));
util.assert(stack.length === 1, "Unmatched <[ in macro");
return stack.top;
},
/** /**
* Returns an object representing a Node's computed CSS style. * Returns an object representing a Node's computed CSS style.
* *