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:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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> " + maps[i].names[j].replace(/</g, "<").replace(/>/g, ">") + "</td>"
|
||||
if (maps[i].rhs)
|
||||
list += "<td> " + maps[i].rhs.replace(/</g, "<").replace(/>/g, ">") + "</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
|
||||
}
|
||||
));
|
||||
//}}}
|
||||
//}}}
|
||||
|
||||
Reference in New Issue
Block a user