diff --git a/content/commands.js b/content/commands.js index 190546d8..fe04a4e0 100644 --- a/content/commands.js +++ b/content/commands.js @@ -139,7 +139,7 @@ liberator.Commands = function () //{{{ var exCommands = []; - function getUserCommands(name) + function getMatchingUserCommands(name) { var matches = []; for (var i = 0; i < exCommands.length; i++) @@ -160,18 +160,6 @@ liberator.Commands = function () //{{{ return matches; } - function removeUserCommand(name) - { - for (var i = 0; i < exCommands.length; i++) - { - if (exCommands[i].isUserCommand && exCommands[i].name == name) - { - exCommands.splice(i, 1); - break; - } - } - } - /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ @@ -244,7 +232,7 @@ liberator.Commands = function () //{{{ } else { - removeUserCommand(command.name); + this.removeUserCommand(command.name); break; } } @@ -265,6 +253,30 @@ liberator.Commands = function () //{{{ return null; }, + getUserCommand: function (name) + { + for (var i = 0; i < exCommands.length; i++) + { + if (exCommands[i].isUserCommand && exCommands[i].hasName(name)) + return exCommands[i]; + } + + return null; + }, + + getUserCommands: function () + { + var userCommands = []; + + for (var i = 0; i < exCommands.length; i++) + { + if (exCommands[i].isUserCommand) + userCommands.push(exCommands[i]); + } + + return userCommands; + }, + // in '-quoted strings, only ' and \ itself are escaped // in "-quoted strings, also ", \n and \t are translated // in non-quoted strings everything is taken literally apart from "\ " and "\\" @@ -287,7 +299,7 @@ liberator.Commands = function () //{{{ // @param allowUnknownOptions: -foo won't result in an error, if -foo isn't // specified in "options" // TODO: should it handle comments? - parseArgs: function (str, options, argCount, allowUnknownOptions) + parseArgs: function (str, options, argCount, allowUnknownOptions) //{{{ { // returns [count, parsed_argument] function getNextArg(str) @@ -585,7 +597,7 @@ liberator.Commands = function () //{{{ } return args; - }, + }, //}}} // return [null, null, null, null, heredoc_tag || false]; // [count, cmd, special, args] = match; @@ -626,7 +638,20 @@ liberator.Commands = function () //{{{ matches[3] = ""; return matches; + }, + + removeUserCommand: function (name) + { + for (var i = 0; i < exCommands.length; i++) + { + if (exCommands[i].isUserCommand && exCommands[i].hasName(name)) + { + exCommands.splice(i, 1); + break; + } + } } + }; /////////////////////////////////////////////////////////////////////////////}}} @@ -664,7 +689,7 @@ liberator.Commands = function () //{{{ } else { - var cmdlist = getUserCommands(cmd); + var cmdlist = getMatchingUserCommands(cmd); if (cmdlist.length > 0) { var str = ":" + liberator.util.escapeHTML(liberator.commandline.getCommand()) + "
" + @@ -688,32 +713,47 @@ liberator.Commands = function () //{{{ /*options: [[["-nargs"], OPTION_STRING, function (arg) { return /^(0|1|\*|\?|\+)$/.test(arg); }], [["-bang"], OPTION_NOARG], [["-bar"], OPTION_NOARG]] */ + completer: function (filter) + { + return liberator.completion.userCommand(filter); + } }); commandManager.add(["comc[lear]"], "Delete all user-defined commands", function () { - var commands = getUserCommands(); - for (var i = 0; i < commands.length; i++) - removeUserCommand(commands[i].name); + liberator.commands.getUserCommands().forEach(function (cmd) { + liberator.commands.removeUserCommand(cmd.name); + }); }, { argCount: "0" }); - // TODO: complete with user-defined commands commandManager.add(["delc[ommand]"], "Delete the specified user-defined command", function (args) { - // TODO: add getUserCommand, removeUserCommands, or similar, and make them 'public'? - var cmd = args.arguments[0]; - var commands = getUserCommands(cmd); - if (commands.length == 1 && cmd == commands[0].name) - removeUserCommand(commands[0].name); - else - liberator.echoerr("E184: No such user-defined command: " + cmd); + var name = args.arguments[0]; + var cmdlist = liberator.commands.getUserCommands(); + + for (var i = 0; i < cmdlist.length; i++) + { + if (cmdlist[i].name == name) + { + liberator.commands.removeUserCommand(name); + return; + } + } + + liberator.echoerr("E184: No such user-defined command: " + name); }, - { argCount: "1" }); + { + argCount: "1", + completer: function (filter) + { + return liberator.completion.userCommand(filter); + } + }); //}}} diff --git a/content/completion.js b/content/completion.js index da216688..948ef738 100644 --- a/content/completion.js +++ b/content/completion.js @@ -165,23 +165,6 @@ liberator.Completion = function () //{{{ return buildLongestCommonSubstring(array, filter); }, - command: function (filter) - { - var completions = []; - - if (!filter) - { - for (var command in liberator.commands) - completions.push([command.name, command.description]); - return [0, completions]; - } - - for (var command in liberator.commands) - completions.push([command.longNames, command.description]); - - return [0, buildLongestStartingSubstring(completions, filter)]; - }, - // FIXME: items shouldn't be [[[a], b]], but [[a, b]] and only mapped if at all for bLCS --mst buffer: function (filter) { @@ -219,6 +202,58 @@ liberator.Completion = function () //{{{ return [0, buildLongestCommonSubstring(items, filter)]; }, + command: function (filter) + { + var completions = []; + + if (!filter) + { + for (var command in liberator.commands) + completions.push([command.name, command.description]); + return [0, completions]; + } + + for (var command in liberator.commands) + completions.push([command.longNames, command.description]); + + return [0, buildLongestStartingSubstring(completions, filter)]; + }, + + // TODO: support file:// and \ or / path separators on both platforms + // if "tail" is true, only return names without any directory components + file: function (filter, tail) + { + var dir = "", compl = ""; + var matches = filter.match(/^(.*[\/\\])?(.*?)$/); + if (matches) + { + dir = matches[1] || ""; // "" is expanded inside readDirectory to the current dir + compl = matches[2] || ""; + } + + var files = [], mapped = []; + try + { + files = liberator.io.readDirectory(dir); + mapped = files.map(function (file) { + return [tail ? file.leafName : (dir + file.leafName), file.isDirectory() ? "Directory" : "File"]; + }).sort(function (a, b) { + return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0; + }).sort(function (a, b) { + return a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0; + }); + } + catch (e) + { + return [0, []]; + } + + if (tail) + return [dir.length, buildLongestStartingSubstring(mapped, compl)]; + else + return [0, buildLongestStartingSubstring(mapped, filter)]; + }, + javascript: function (str) { var matches = str.match(/^(.*?)(\s*\.\s*)?(\w*)$/); @@ -297,41 +332,6 @@ liberator.Completion = function () //{{{ return [offset, buildLongestStartingSubstring(completions, filter)]; }, - // TODO: support file:// and \ or / path separators on both platforms - // if "tail" is true, only return names without any directory components - file: function (filter, tail) - { - var dir = "", compl = ""; - var matches = filter.match(/^(.*[\/\\])?(.*?)$/); - if (matches) - { - dir = matches[1] || ""; // "" is expanded inside readDirectory to the current dir - compl = matches[2] || ""; - } - - var files = [], mapped = []; - try - { - files = liberator.io.readDirectory(dir); - mapped = files.map(function (file) { - return [tail ? file.leafName : (dir + file.leafName), file.isDirectory() ? "Directory" : "File"]; - }).sort(function (a, b) { - return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0; - }).sort(function (a, b) { - return a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0; - }); - } - catch (e) - { - return [0, []]; - } - - if (tail) - return [dir.length, buildLongestStartingSubstring(mapped, compl)]; - else - return [0, buildLongestStartingSubstring(mapped, filter)]; - }, - macro: function (filter) { var macros = []; @@ -400,6 +400,17 @@ liberator.Completion = function () //{{{ return [0, completions]; }, + stylesheet: function (filter) + { + var stylesheets = getAllStyleSheets(window.content); + + stylesheets = liberator.buffer.alternateStyleSheets.map(function (stylesheet) { + return [stylesheet.title, stylesheet.href || "inline"]; + }); + + return [0, this.filter(stylesheets, filter)]; + }, + // filter a list of urls // // may consist of search engines, filenames, bookmarks and history, @@ -462,15 +473,11 @@ liberator.Completion = function () //{{{ return [start, completions.concat(urlCompletionCache)]; }, - stylesheet: function (filter) + userCommand: function (filter) { - var stylesheets = getAllStyleSheets(window.content); - - stylesheets = liberator.buffer.alternateStyleSheets.map(function (stylesheet) { - return [stylesheet.title, stylesheet.href || "inline"]; - }); - - return [0, this.filter(stylesheets, filter)]; + var commands = liberator.commands.getUserCommands(); + commands = commands.map(function (command) { return [command.name, ""]; }); + return [0, this.filter(commands, filter)]; }, userMapping: function (filter, modes)