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

add initial (very rough) implementations of :map, :mapclear and :unmap

This commit is contained in:
Doug Kearns
2007-07-21 16:42:38 +00:00
parent 039544a697
commit 38fd04be35
2 changed files with 319 additions and 66 deletions

View File

@@ -187,6 +187,7 @@ function Commands() //{{{
if (ex_commands[i].hasName(name))
return ex_commands[i];
}
return null;
}
@@ -505,6 +506,73 @@ function Commands() //{{{
"The special version <code class=\"command\">:javascript!</code> will open the javascript console of Firefox."
}
));
addDefaultCommand(new Command(["map"],
// 0 args -> list all maps
// 1 arg -> list the maps starting with args
// 2 args -> map arg1 to arg*
function(args)
{
if (args.length == 0)
{
vimperator.mappings.list(vimperator.modes.NORMAL);
return;
}
var matches = args.match(/^([^ ]+)(?:\s+(.+))?$/);
var [lhs, rhs] = [matches[1], matches[2]];
if (rhs)
{
if (/^:/.test(rhs))
{
vimperator.mappings.add(
new Map(vimperator.modes.NORMAL, [lhs], function() { execute(rhs); }, { rhs: rhs })
);
}
else
{
var map = vimperator.mappings.get(vimperator.modes.NORMAL, rhs);
// create a new Map for {lhs} with the same action as
// {rhs}...until we have feedkeys().
// NOTE: Currently only really useful for static use ie. from
// the RC file
if (map)
vimperator.mappings.add(
new Map(vimperator.modes.NORMAL, [lhs], map.action, { rhs: rhs })
);
else
vimperator.echoerr("E475: Invalid argument: " + "{rhs} must be a existing singular mapping");
}
}
else
{
// FIXME: no filtering for now
vimperator.mappings.list(vimperator.modes.NORMAL, lhs);
}
},
{
usage: ["map {lhs} {rhs}", "map {lhs}", "map"],
short_help: "Map the key sequence {lhs} to {rhs}",
help: ""
}
));
addDefaultCommand(new Command(["mapc[lear]"],
function(args)
{
if (args.length > 0)
{
vimperator.echoerr("E474: Invalid argument");
return;
}
vimperator.mappings.removeAll(vimperator.modes.NORMAL);
},
{
short_help: "Remove all mappings",
help: ""
}
));
addDefaultCommand(new Command(["ma[rk]"],
function(args)
{
@@ -891,6 +959,28 @@ function Commands() //{{{
help: "TODO."
}
));
addDefaultCommand(new Command(["unm[ap]"],
function(args)
{
if (args.length == 0)
{
vimperator.echoerr("E474: Invalid argument");
return;
}
var lhs = args;
if (vimperator.mappings.hasMap(vimperator.modes.NORMAL, lhs))
vimperator.mappings.remove(vimperator.modes.NORMAL, lhs);
else
vimperator.echoerr("E31: No such mapping");
},
{
usage: ["unm[ap] {lhs}"],
short_help: "Remove the mapping of {lhs}",
help: ""
}
));
addDefaultCommand(new Command(["ve[rsion]"],
function(args, special)
{

View File

@@ -26,14 +26,14 @@ the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
}}} ***** END LICENSE BLOCK *****/
function Map(mode, cmds, act, extra_info) //{{{
function Map(mode, cmds, action, extra_info) //{{{
{
if (!mode || (!cmds || !cmds.length) || !act)
if (!mode || (!cmds || !cmds.length) || !action)
return null;
this.mode = mode;
this.names = cmds;
this.action = act;
this.action = action;
this.usage = [this.names[0]];
@@ -56,6 +56,8 @@ function Map(mode, cmds, act, extra_info) //{{{
this.help = extra_info.help || null;
this.short_help = extra_info.short_help || null;
this.rhs = extra_info.rhs || null;
// TODO: are these limited to HINTS mode?
// Only set for hints maps
this.cancel_mode = extra_info.cancel_mode || false;
@@ -64,6 +66,17 @@ function Map(mode, cmds, act, extra_info) //{{{
}
Map.prototype.hasName = function(name)
{
for (var i = 0; i < this.names.length; i++)
{
if (this.names[i] == name)
return true;
}
return false;
}
// Since we will add many Map-objects, we add some functions as prototypes
// this will ensure we only have one copy of each function, not one for each object
Map.prototype.execute = function(motion, count, argument)
@@ -96,6 +109,7 @@ function Mappings() //{{{
////////////////////// PRIVATE SECTION /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
// TODO: initialize empty map tables?
var main = []; // array of default Map() objects
var user = []; // array of objects created by :map
@@ -103,33 +117,56 @@ function Mappings() //{{{
{
if (!main[map.mode])
main[map.mode] = [];
main[map.mode].push(map);
}
function getFrom(mode, cmd, stack)
function getMap(mode, cmd, stack)
{
if (!stack || !stack[mode] || !stack[mode].length)
return;
var substack = stack[mode];
var stack_length = substack.length;
for (var i = 0; i < stack_length; i++)
for (var i = 0; i < substack.length; i++)
{
for (var j = 0; j < substack[i].names.length; j++)
if (substack[i].names[j] == cmd)
return substack[i];
}
return null;
}
function removeMap(mode, cmd)
{
var maps = user[mode];
var names;
for (var i = 0; i < maps.length; i++)
{
names = maps[i].names;
for (var j = 0; j < names.length; j++)
{
if (names[j] == cmd)
{
names.splice(j, 1)
if (names.length == 0)
maps.splice(i, 1);
return;
}
}
}
}
function mappingsIterator(mode)
{
var mappings;
var mappings = main[mode];
// FIXME: initialize empty map tables
if (user[mode])
mappings = user[mode].concat(main[mode]);
else
mappings = main[mode]
//// FIXME: do we want to document user commands by default?
//if (user[mode])
// mappings = user[mode].concat(main[mode]);
//else
// mappings = main[mode]
for (var i = 0; i < mappings.length; i++)
yield mappings[i];
@@ -158,39 +195,46 @@ function Mappings() //{{{
return mappingsIterator(mode);
}
this.hasMap = function(mode, cmd)
{
var user_maps = user[mode];
for (var i = 0; i < user_maps.length; i++)
{
if (user_maps[i].names.indexOf(cmd) != -1)
return true;
}
return false;
}
this.add = function(map)
{
if (!map)
return false;
if (!user[map.mode])
user[map.mode] = [];
user[map.mode].push(map);
for (var i = 0; i < map.names.length; i++)
removeMap(map.mode, map.names[i]);
return true;
user[map.mode].push(map);
}
// FIXME: this doesn't work
this.remove = function(map)
this.remove = function(mode, cmd)
{
var index;
removeMap(mode, cmd);
}
if (!map || !(index = user[map.mode].indexOf(map)))
return false;
user[map.mode].splice(index, 1);
return true;
this.removeAll = function(mode)
{
user[mode] = [];
}
this.get = function(mode, cmd)
{
if (!mode || !cmd)
return null;
var map = getMap(mode, cmd, user);
var map = getFrom(mode, cmd, user);
if (!map)
map = getFrom(mode, cmd, main);
map = getMap(mode, cmd, main);
return map;
}
@@ -201,9 +245,6 @@ function Mappings() //{{{
var mappings = [];
var matches = [];
if (!mode || !cmd)
return matches;
if (user[mode])
mappings = user[mode].concat(main[mode]);
else
@@ -222,6 +263,35 @@ function Mappings() //{{{
return matches;
}
// TODO: implement filtering
this.list = function(mode, filter)
{
var maps = user[mode];
if (!maps || maps.length == 0)
{
vimperator.echo("No mappings found");
return;
}
var list = "<table>";
for (var i = 0; i < maps.length; i++)
{
for (var j = 0; j < maps[i].names.length; j++)
{
list += "<tr>";
list += "<td>&nbsp;" + maps[i].names[j].replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</td>"
if (maps[i].rhs)
list += "<td>&nbsp;" + maps[i].rhs.replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</td>"
list += "</tr>";
}
}
list += "</table>";
vimperator.commandline.echo(list, true); // TODO: force of multiline widget a better way
}
/////////////////////////////////////////////////////////////////////////////}}}
////////////////////// DEFAULT MAPPINGS ////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{
@@ -800,135 +870,228 @@ function Mappings() //{{{
// action keys
addDefaultMap(new Map(vimperator.modes.HINTS, ["o"],
function() { vimperator.hints.openHints(false, false); },
{ cancel_mode: true, always_active: false }
{
cancel_mode: true,
always_active: false
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["t"],
function() { vimperator.hints.openHints(true, false); },
{ cancel_mode: true, always_active: false }
{
cancel_mode: true,
always_active: false
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-w>"],
function() { vimperator.hints.openHints(false, true ); },
{ cancel_mode: true, always_active: false }
{
cancel_mode: true,
always_active: false
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["s"],
function() { vimperator.echoerr('Saving of links not yet implemented'); },
{ cancel_mode: true, always_active: false }
{
cancel_mode: true,
always_active: false
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["y"],
function() { vimperator.hints.yankUrlHints(); },
{ cancel_mode: true, always_active: false }
{
cancel_mode: true,
always_active: false
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["Y"],
function() { vimperator.hints.yankTextHints(); },
{ cancel_mode: true, always_active: false }
{
cancel_mode: true,
always_active: false
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, [","],
function() { vimperator.input.buffer += ','; vimperator.hints.setCurrentState(0); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, [":"],
function() { vimperator.commandline.open(':', '', vimperator.modes.EX); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
// movement keys
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-e>"],
function() { scrollBufferRelative(0, 1); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-y>"],
function() { scrollBufferRelative(0, -1); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<Home>"],
function() { scrollBufferAbsolute(-1, 0); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<End>"],
function() { scrollBufferAbsolute(-1, 100); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-b>"],
function() { goDoCommand('cmd_scrollPageUp'); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<PageUp>"],
function() { goDoCommand('cmd_scrollPageUp'); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-f>"],
function() { goDoCommand('cmd_scrollPageDown'); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<PageDown>"],
function() { goDoCommand('cmd_scrollPageDown'); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<Left>"],
function() { scrollBufferRelative(-1, 0); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<Down>"],
function() { scrollBufferRelative(0, 1); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<Up>"],
function() { scrollBufferRelative(0, -1); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<Right>"],
function() { scrollBufferRelative(1, 0); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
// tab management
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-n>"],
function() { vimperator.tabs.select('+1', true); },
{ cancel_mode: true, always_active: true }
{
cancel_mode: true,
always_active: true
}
)); // same as gt, but no count supported
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-p>"],
function() { vimperator.tabs.select('-1', true); },
{ cancel_mode: true, always_active: true }
{
cancel_mode: true,
always_active: true
}
));
// navigation
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-o>"],
function() { vimperator.history.stepTo(vimperator.input.count > 0 ? -1 * vimperator.input.count : -1); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-i>"],
function() { vimperator.history.stepTo(vimperator.input.count > 0 ? vimperator.input.count : 1); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-h>"],
function() { vimperator.history.stepTo(vimperator.input.count > 0 ? -1 * vimperator.input.count : -1); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-l>"],
function() { vimperator.history.stepTo(vimperator.input.count > 0 ? vimperator.input.count : 1); },
{ cancel_mode: false, always_active: true }
{
cancel_mode: false,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-d>"],
function() { vimperator.tabs.remove(getBrowser().mCurrentTab, vimperator.input.count, false, 0); },
{ cancel_mode: true, always_active: true }
{
cancel_mode: true,
always_active: true
}
));
// cancel_mode hint mode keys
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-c>"],
function() { ; },
{ cancel_mode: true, always_active: true }
{
cancel_mode: true,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-g>"],
function() { ; },
{ cancel_mode: true, always_active: true }
{
cancel_mode: true,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<C-[>"],
function() { ; },
{ cancel_mode: true, always_active: true }
{
cancel_mode: true,
always_active: true
}
));
addDefaultMap(new Map(vimperator.modes.HINTS, ["<Esc>"],
function() { ; },
{ cancel_mode: true, always_active: true }
{
cancel_mode: true,
always_active: true
}
));
//}}}
//}}}