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

Generally niftier :mkv

This commit is contained in:
Kris Maglione
2008-10-30 03:31:19 +00:00
parent bfe0530209
commit a53b702200
8 changed files with 155 additions and 123 deletions

View File

@@ -857,7 +857,16 @@ function Buffer() //{{{
bang: true, bang: true,
hereDoc: true, hereDoc: true,
literal: true, literal: true,
options: [[["-name", "-n"], commands.OPTION_STRING]] options: [[["-name", "-n"], commands.OPTION_STRING]],
serial: function () [
{
command: this.name,
bang: true,
options: sty.name ? {"-name": sty.name} : {},
arguments: [sty.sites.join(",")],
literalArg: sty.css
} for ([k, sty] in styles.userSheets)
]
}); });
commands.add(["dels[tyle]"], commands.add(["dels[tyle]"],

View File

@@ -81,6 +81,7 @@ function Command(specs, description, action, extraInfo) //{{{
this.bang = extraInfo.bang || false; this.bang = extraInfo.bang || false;
this.count = extraInfo.count || false; this.count = extraInfo.count || false;
this.literal = extraInfo.literal || false; this.literal = extraInfo.literal || false;
this.serial = extraInfo.serial;
this.isUserCommand = extraInfo.isUserCommand || false; this.isUserCommand = extraInfo.isUserCommand || false;
this.replacementText = extraInfo.replacementText || null; this.replacementText = extraInfo.replacementText || null;
@@ -166,25 +167,15 @@ function Commands() //{{{
function getMatchingUserCommands(name, filter) function getMatchingUserCommands(name, filter)
{ {
var matches = []; var matches = [];
outer:
for (let [,cmd] in Iterator(exCommands)) for (let [,cmd] in Iterator(exCommands))
{ {
if (cmd.isUserCommand) if (cmd.isUserCommand)
{ {
for (let [k, v] in Iterator(filter)) if (!name || cmd.name.match("^" + name))
{ {
if (v != null && cmd[k] != v) if (util.map(filter, function (f) f).every(function ([k, v]) v == null || cmd[k] == v))
continue outer;
}
if (name)
{
if (cmd.name.match("^" + name))
matches.push(cmd); matches.push(cmd);
} }
else
{
matches.push(cmd);
}
} }
} }
return matches; return matches;
@@ -199,6 +190,17 @@ function Commands() //{{{
return NaN; return NaN;
} }
function quote(q, list) list.reduce(function (acc, [k,v])
{
v = "\\" + (v || k);
return function (str) acc(String.replace(str, k, v, "g"))
}, function (val) q + val + q);
const quoteArg = {
'"': quote('"', [["\n", "n"], ["\t", "t"], ['"'], ["\\"]]),
"'": quote("'", [["\\"], ["'"]]),
"": quote("", [["\\"], [" "]])
}
const ArgType = new Struct("description", "parse"); const ArgType = new Struct("description", "parse");
const argTypes = [ const argTypes = [
null, null,
@@ -291,6 +293,26 @@ function Commands() //{{{
return true; return true;
}, },
commandToString: function (args)
{
let res = [args.command + (args.bang ? "!" : "")];
function quote(str) quoteArg[/\s/.test(str) ? '"' : ""](str);
for (let [opt, val] in Iterator(args.options || {}))
{
res.push(opt);
if (val != null)
res.push(quote(val));
}
for (let [,arg] in Iterator(args.arguments || []))
res.push(quote(arg));
let str = args.literalArg;
if (str)
res.push(/\n/.test(str) ? "<<EOF\n" + str + "EOF" : str);
return res.join(" ");
},
get: function (name) get: function (name)
{ {
for (let i = 0; i < exCommands.length; i++) for (let i = 0; i < exCommands.length; i++)
@@ -350,20 +372,6 @@ function Commands() //{{{
// TODO: should it handle comments? // TODO: should it handle comments?
parseArgs: function (str, options, argCount, allowUnknownOptions, literal, complete) parseArgs: function (str, options, argCount, allowUnknownOptions, literal, complete)
{ {
function quoteArg(quote)
{
switch (quote)
{
case "'":
return function (str) "'" + str.replace(/[\\']/g, "\\$&") + "'";
case '"':
return function (str) '"' + str.replace(/[\\"\t\n]/g,
function (c) (c == "\n" ? "\\n" : c == "\t" ? "\\t" : "\\" + c));
default:
return function (str) str.replace(/[\\ ]/g, "\\$&");
}
}
// returns [count, parsed_argument] // returns [count, parsed_argument]
function getNextArg(str) function getNextArg(str)
{ {
@@ -546,8 +554,8 @@ function Commands() //{{{
let compl = opt[3] || []; let compl = opt[3] || [];
if (typeof compl == "function") if (typeof compl == "function")
compl = compl(); compl = compl();
let filter = quoteArg(sub[optname.length + 1]) let quote = quoteArg[sub[optname.length + 1]] || quoteArg[""];
return [i + optname.length + 1, completion.filter(compl.map(filter), filter(arg))]; return [i + optname.length + 1, completion.filter(compl.map(quote), quote(arg))];
} }
if (!invalid) if (!invalid)
@@ -668,6 +676,8 @@ function Commands() //{{{
return matches; return matches;
}, },
get quoteArg() quoteArg,
removeUserCommand: function (name) removeUserCommand: function (name)
{ {
for (let i = 0; i < exCommands.length; i++) for (let i = 0; i < exCommands.length; i++)
@@ -690,7 +700,7 @@ function Commands() //{{{
if (res == undefined) // Ignore anything undefined if (res == undefined) // Ignore anything undefined
res = "<" + token + ">"; res = "<" + token + ">";
if (quote && typeof res != "number") if (quote && typeof res != "number")
return '"' + String.replace(res, '"', '\\"', "g") + '"'; return quoteArg['"'](res);
return res; return res;
}); });
} }
@@ -782,6 +792,20 @@ function Commands() //{{{
[["-nargs"], commandManager.OPTION_STRING, function (arg) /^[01*?+]$/.test(arg), ["0", "1", "*", "?", "+"]], [["-nargs"], commandManager.OPTION_STRING, function (arg) /^[01*?+]$/.test(arg), ["0", "1", "*", "?", "+"]],
[["-bang"], commandManager.OPTION_NOARG], [["-bang"], commandManager.OPTION_NOARG],
[["-count"], commandManager.OPTION_NOARG], [["-count"], commandManager.OPTION_NOARG],
],
serial: function () [
{
command: this.name,
// Yeah, this is a bit scary. Perhaps I'll fix it when I'm
// awake.
options: util.Array.assocToObj(util.map({argCount: "-nargs", bang: "-bang", count: "-count"},
function ([k, v]) k in cmd && cmd[k] != "0" && [v, typeof cmd[k] == "boolean" ? null : cmd[k]])
.filter(function(k) k)),
arguments: [cmd.name],
literalArg: cmd.replacementText
}
for ([k,cmd] in Iterator(exCommands))
if (cmd.isUserCommand && cmd.replacementText)
] ]
}); });

View File

@@ -147,6 +147,15 @@ function Editor() //{{{
{ flags: Mappings.flags.MOTION | Mappings.flags.COUNT }); { flags: Mappings.flags.MOTION | Mappings.flags.COUNT });
} }
// For the record, some of this code I've just finished throwing
// away makes me want to pull someone else's hair out. --Kris
function abbrevs()
{
for (let [lhs, abbr] in Iterator(abbrev))
for (let [,rhs] in Iterator(abbr))
yield [lhs, rhs];
}
// mode = "i" -> add :iabbrev, :iabclear and :iunabbrev commands // mode = "i" -> add :iabbrev, :iabclear and :iunabbrev commands
function addAbbreviationCommands(ch, modeDescription) function addAbbreviationCommands(ch, modeDescription)
{ {
@@ -157,20 +166,25 @@ function Editor() //{{{
"Abbreviate a key sequence" + modeDescription, "Abbreviate a key sequence" + modeDescription,
function (args) function (args)
{ {
args = args.string; let lhs = args.arguments[0];
let rhs = args.literalArg;
if (!args)
{
editor.listAbbreviations(mode, "");
return;
}
var matches = args.match(/^(\S+)(?:\s+(.+))?$/);
var [lhs, rhs] = [matches[1], matches[2]];
if (rhs) if (rhs)
editor.addAbbreviation(mode, lhs, rhs); editor.addAbbreviation(mode, lhs, rhs);
else else
editor.listAbbreviations(mode, lhs); editor.listAbbreviations(mode, lhs || "");
},
{
argCount: 1,
literal: true,
serial: function () [
{
command: this.name,
arguments: [lhs],
literalArg: abbr[1]
}
for ([lhs, abbr] in abbrevs())
if (abbr[0] == mode)
]
}); });
commands.add([ch ? ch + "una[bbrev]" : "una[bbreviate]"], commands.add([ch ? ch + "una[bbrev]" : "una[bbreviate]"],
@@ -892,21 +906,6 @@ function Editor() //{{{
// Abbreviations {{{ // Abbreviations {{{
abbreviations: {
__iterator__: function ()
{
var tmpCmd;
for (let lhs in abbrev)
{
for (let i = 0; i < abbrev[lhs].length; i++)
{
tmpCmd = (abbrev[lhs][i][0] == "!") ? "abbreviate" : abbrev[lhs][i][0] + "abbrev";
yield (tmpCmd + " " + lhs + " " + abbrev[lhs][i][1] + "\n");
}
}
}
},
// filter is i, c or "!" (insert or command abbreviations or both) // filter is i, c or "!" (insert or command abbreviations or both)
listAbbreviations: function (filter, lhs) listAbbreviations: function (filter, lhs)
{ {
@@ -914,10 +913,11 @@ function Editor() //{{{
{ {
if (abbrev[lhs]) if (abbrev[lhs])
{ {
for (let i = 0; i < abbrev[lhs].length; i++) for (let [,abbr] in Iterator(abbrev[lhs]))
{ {
if (abbrev[lhs][i][0] == filter) if (abbr[0] == filter)
liberator.echo(abbrev[lhs][i][0] + " " + lhs + " " + abbrev[lhs][i][1]); liberator.echo(abbr[0] + " " + lhs + " " + abbr[1]);
// Is it me, or is this clearly very wrong? --Kris
return true; return true;
} }
} }
@@ -932,14 +932,13 @@ function Editor() //{{{
let list = let list =
<table> <table>
{ {
template.map(abbrev, function ([lhs, rhs]) template.map(abbrevs(), function ([lhs, rhs])
template.map(rhs, function (abbr) searchFilter.indexOf(rhs[0]) < 0 ? undefined :
searchFilter.indexOf(abbr[0]) < 0 ? undefined : <tr>
<tr> <td>{rhs[0]}</td>
<td>{abbr[0]}</td> <td>{lhs}</td>
<td>{lhs}</td> <td>{rhs[1]}</td>
<td>{abbr[1]}</td> </tr>)
</tr>))
} }
</table>; </table>;
if (list.*.length()) if (list.*.length())

View File

@@ -228,50 +228,31 @@ function IO() //{{{
return; return;
} }
let line = "\" " + liberator.version + "\n"; let lines = [['"' + liberator.version]];
line += "\" Mappings\n";
[[[modes.NORMAL], ""], // FIXME: Use a set/specifiable list here:
[[modes.COMMAND_LINE], "c"], for (let cmd in commands)
[[modes.INSERT, modes.TEXTAREA], "i"]].forEach(function ([modes, modechar]) {
// NOTE: names.length is always 1 on user maps. If that changes, also fix getUserIterator and v.m.list
for (let map in mappings.getUserIterator(modes))
line += modechar + (map.noremap ? "noremap" : "map") + " " + map.names[0] + " " + map.rhs + "\n";
});
line += "\n\" Options\n";
for (let option in options)
{ {
// TODO: options should be queried for this info if (cmd.serial)
// TODO: string/list options might need escaping in future lines.push(cmd.serial().map(commands.commandToString));
if (!/fullscreen|usermode/.test(option.name) && option.value != option.defaultValue)
{
if (option.type == "boolean")
line += "set " + (option.value ? option.name : "no" + option.name) + "\n";
else
line += "set " + option.name + "=" + option.value + "\n";
}
} }
lines = util.Array.flatten(lines);
// :mkvimrc doesn't save autocommands, so we don't either - remove this code at some point // :mkvimrc doesn't save autocommands, so we don't either - remove this code at some point
// line += "\n\" Auto-Commands\n"; // line += "\n\" Auto-Commands\n";
// for (let item in autocommands) // for (let item in autocommands)
// line += "autocmd " + item.event + " " + item.pattern.source + " " + item.command + "\n"; // line += "autocmd " + item.event + " " + item.pattern.source + " " + item.command + "\n";
line += "\n\" Abbreviations\n";
for (let abbrCmd in editor.abbreviations)
line += abbrCmd;
// if (mappings.getMapLeader() != "\\") // if (mappings.getMapLeader() != "\\")
// line += "\nlet mapleader = \"" + mappings.getMapLeader() + "\"\n"; // line += "\nlet mapleader = \"" + mappings.getMapLeader() + "\"\n";
// source a user .vimperatorrc file // source a user .vimperatorrc file
line += "\nsource! " + filename + ".local\n"; lines.push("\nsource! " + filename + ".local");
line += "\n\" vim: set ft=vimperator:"; lines.push("\n\" vim: set ft=vimperator:");
try try
{ {
io.writeFile(file, line); io.writeFile(file, lines.join("\n"));
} }
catch (e) catch (e)
{ {

View File

@@ -132,30 +132,10 @@ function Mappings() //{{{
function mappingsIterator(modes, stack) function mappingsIterator(modes, stack)
{ {
var output; modes = modes.slice();
var maps = stack[modes[0]]; return (map for ([i, map] in Iterator(stack[modes.shift()]))
if (modes.every(function (mode) stack[mode].some(
for (let i = 0; i < maps.length; i++) function (m) m.rhs == map.rhs && m.names[0] == map.names[0]))))
{
output = true;
for (let index = 1; index < modes.length; index++) // check other modes
{
output = false; // toggle false, only true whan also found in this mode
for (let j = 0; j < user[modes[index]].length; j++) // maps
{
// NOTE: when other than user maps, there might be more than only one names[x].
// since only user mappings gets queried here, only names[0] gets checked for equality.
if (maps[i].rhs == user[modes[index]][j].rhs && maps[i].names[0] == user[modes[index]][j].names[0])
{
output = true;
break; // found on this mode - check next mode, if there is one, where it could still fail...
}
}
break; // not found in this mode -> map wont' match all modes...
}
if (output)
yield maps[i];
}
} }
function addMapCommands(ch, modes, modeDescription) function addMapCommands(ch, modes, modeDescription)
@@ -203,7 +183,20 @@ function Mappings() //{{{
[["<silent>", "<Silent>"], commands.OPTION_NOARG] [["<silent>", "<Silent>"], commands.OPTION_NOARG]
], ],
argCount: 1, argCount: 1,
literal: true literal: true,
serial: function () {
let noremap = this.name.indexOf("noremap") > -1;
return [
{
command: this.name,
options: map.silent ? {"<silent>": null} : {},
arguments: [map.names[0]],
literalArg: map.rhs
}
for (map in mappingsIterator(modes, user))
if (map.rhs && map.noremap == noremap)
]
}
}; };
commands.add([ch ? ch + "m[ap]" : "map"], commands.add([ch ? ch + "m[ap]" : "map"],

View File

@@ -799,7 +799,16 @@ function Options() //{{{
} }
} }
return [len, completion.filter(completions, filter, true)]; return [len, completion.filter(completions, filter, true)];
} },
serial: function () [
{
command: this.name,
literalArg: opt.type == "boolean" ? (opt.value ? "" : "no") + opt.name
: opt.name + "=" + opt.value
}
for (opt in options)
if (!opt.getter && opt.value != opt.defaultValue && (opt.scope & options.OPTION_SCOPE_GLOBAL))
]
}); });
commands.add(["unl[et]"], commands.add(["unl[et]"],

View File

@@ -53,7 +53,7 @@ const template = {
// Vim generally doesn't like /foo*/, because */ looks like a comment terminator. // Vim generally doesn't like /foo*/, because */ looks like a comment terminator.
// Using /foo*(:?)/ instead. // Using /foo*(:?)/ instead.
if (processStrings) if (processStrings)
return <span class="hl-Function">{String(arg).replace(/\{(.|\n)*(?:)/, "{ ... }")}</span>; return <span class="hl-Function">{String(arg).replace(/\{(.|\n)*(?:)/g, "{ ... }")}</span>;
return <>{arg}</>; return <>{arg}</>;
case "undefined": case "undefined":
return <span class="hl-Null">{arg}</span>; return <span class="hl-Null">{arg}</span>;

View File

@@ -29,6 +29,15 @@ the terms of any one of the MPL, the GPL or the LGPL.
const util = { //{{{ const util = { //{{{
Array: { Array: {
// [["a", "b"], ["c", "d"]] -> {a: "b", c: "d"}
// From Common Lisp, more or less
assocToObj: function (assoc)
{
let obj = {};
assoc.forEach(function ([k, v]) { obj[k] = v });
return obj;
},
// flatten an array: [["foo", "bar"], ["baz"]] -> ["foo", "bar", "baz"] // flatten an array: [["foo", "bar"], ["baz"]] -> ["foo", "bar", "baz"]
flatten: function (ary) flatten: function (ary)
{ {
@@ -165,7 +174,7 @@ const util = { //{{{
{ {
if (delimiter == undefined) if (delimiter == undefined)
delimiter = '"'; delimiter = '"';
return delimiter + str.replace(/([\\'"])/g, "\\$1").replace("\n", "\\n").replace("\t", "\\t") + delimiter; return delimiter + str.replace(/([\\'"])/g, "\\$1").replace("\n", "\\n", "g").replace("\t", "\\t", "g") + delimiter;
}, },
formatBytes: function (num, decimalPlaces, humanReadable) formatBytes: function (num, decimalPlaces, humanReadable)
@@ -254,6 +263,14 @@ const util = { //{{{
return ret; return ret;
}, },
map: function (obj, fn)
{
let ary = [];
for (let i in Iterator(obj))
ary.push(fn(i));
return ary;
},
// if color = true it uses HTML markup to color certain items // if color = true it uses HTML markup to color certain items
objectToString: function (object, color) objectToString: function (object, color)
{ {