'help' command test
This commit is contained in:
+43
-1
@@ -1,23 +1,65 @@
|
|||||||
|
local SEPARATOR = "________________"
|
||||||
|
SEPARATOR = SEPARATOR..SEPARATOR..SEPARATOR
|
||||||
|
|
||||||
|
console.add_command(
|
||||||
|
"help name:str=''",
|
||||||
|
"Show help infomation for the specified command",
|
||||||
|
function (args, kwargs)
|
||||||
|
local name = args[1]
|
||||||
|
if #name == 0 then
|
||||||
|
local commands = console.get_commands_list()
|
||||||
|
table.sort(commands)
|
||||||
|
return "available commands: "..
|
||||||
|
table.tostring(commands)..
|
||||||
|
"\nuse 'help [command]'"
|
||||||
|
end
|
||||||
|
local command = console.get_command_info(name)
|
||||||
|
if command == nil then
|
||||||
|
return string.format("command %q not found", name)
|
||||||
|
end
|
||||||
|
local where = ""
|
||||||
|
local str = SEPARATOR.."\n"..command.description.."\n"..name.." "
|
||||||
|
for i,arg in ipairs(command.args) do
|
||||||
|
where = where.."\n "..arg.name.." - "..arg.type
|
||||||
|
if arg.optional then
|
||||||
|
str = str.."["..arg.name.."] "
|
||||||
|
where = where.." (optional)"
|
||||||
|
else
|
||||||
|
str = str.."<"..arg.name.."> "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #command.args then
|
||||||
|
str = str.."\nwhere"..where
|
||||||
|
end
|
||||||
|
|
||||||
|
return str.."\n"..SEPARATOR
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
console.add_command(
|
console.add_command(
|
||||||
"tp obj:sel=$obj.id x:num~pos.x y:num~pos.y z:num~pos.z",
|
"tp obj:sel=$obj.id x:num~pos.x y:num~pos.y z:num~pos.z",
|
||||||
|
"Teleport object",
|
||||||
function (args, kwargs)
|
function (args, kwargs)
|
||||||
player.set_pos(unpack(args))
|
player.set_pos(unpack(args))
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
console.add_command(
|
console.add_command(
|
||||||
"echo value:str",
|
"echo value:str",
|
||||||
|
"Print value to the console",
|
||||||
function (args, kwargs)
|
function (args, kwargs)
|
||||||
return args[1]
|
return args[1]
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
console.add_command(
|
console.add_command(
|
||||||
"time.set value:num",
|
"time.set value:num",
|
||||||
|
"Set day time [0..1] where 0 is midnight, 0.5 is noon",
|
||||||
function (args, kwargs)
|
function (args, kwargs)
|
||||||
return world.set_day_time(args[1])
|
return world.set_day_time(args[1])
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
console.add_command(
|
console.add_command(
|
||||||
"fill id:str x:num~pos.x y:num~pos.y z:num~pos.z w:int h:int d:int",
|
"blocks.fill id:str x:num~pos.x y:num~pos.y z:num~pos.z w:int h:int d:int",
|
||||||
|
"Fill specified zone with blocks",
|
||||||
function (args, kwargs)
|
function (args, kwargs)
|
||||||
local name, x, y, z, w, h, d = unpack(args)
|
local name, x, y, z, w, h, d = unpack(args)
|
||||||
local id = block.index(name)
|
local id = block.index(name)
|
||||||
|
|||||||
@@ -32,22 +32,6 @@ void TextBox::draw(const DrawContext* pctx, Assets* assets) {
|
|||||||
|
|
||||||
font = assets->getFont(label->getFontName());
|
font = assets->getFont(label->getFontName());
|
||||||
|
|
||||||
if (autoresize && font) {
|
|
||||||
auto size = getSize();
|
|
||||||
int newy = glm::min(static_cast<int>(parent->getSize().y),
|
|
||||||
static_cast<int>(
|
|
||||||
label->getLinesNumber() *
|
|
||||||
label->getLineInterval() *
|
|
||||||
font->getLineHeight()) + 1
|
|
||||||
);
|
|
||||||
if (newy != static_cast<int>(size.y)) {
|
|
||||||
size.y = newy;
|
|
||||||
setSize(size);
|
|
||||||
if (positionfunc) {
|
|
||||||
pos = positionfunc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isFocused()) {
|
if (!isFocused()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -141,6 +125,24 @@ void TextBox::drawBackground(const DrawContext* pctx, Assets*) {
|
|||||||
void TextBox::refreshLabel() {
|
void TextBox::refreshLabel() {
|
||||||
label->setColor(glm::vec4(input.empty() ? 0.5f : 1.0f));
|
label->setColor(glm::vec4(input.empty() ? 0.5f : 1.0f));
|
||||||
label->setText(getText());
|
label->setText(getText());
|
||||||
|
|
||||||
|
if (autoresize && font) {
|
||||||
|
auto size = getSize();
|
||||||
|
int newy = glm::min(static_cast<int>(parent->getSize().y),
|
||||||
|
static_cast<int>(
|
||||||
|
label->getLinesNumber() *
|
||||||
|
label->getLineInterval() *
|
||||||
|
font->getLineHeight()) + 1
|
||||||
|
);
|
||||||
|
if (newy != static_cast<int>(size.y)) {
|
||||||
|
size.y = newy;
|
||||||
|
setSize(size);
|
||||||
|
if (positionfunc) {
|
||||||
|
pos = positionfunc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (multiline && font) {
|
if (multiline && font) {
|
||||||
setScrollable(true);
|
setScrollable(true);
|
||||||
uint height = label->getLinesNumber() * font->getLineHeight() * label->getLineInterval();
|
uint height = label->getLinesNumber() * font->getLineHeight() * label->getLineInterval();
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ public:
|
|||||||
return Argument {name, type, optional, def, origin, enumname};
|
return Argument {name, type, optional, def, origin, enumname};
|
||||||
}
|
}
|
||||||
|
|
||||||
Command parseScheme(executor_func executor) {
|
Command parseScheme(executor_func executor, std::string_view description) {
|
||||||
std::string name = parseIdentifier(true);
|
std::string name = parseIdentifier(true);
|
||||||
std::vector<Argument> args;
|
std::vector<Argument> args;
|
||||||
std::unordered_map<std::string, Argument> kwargs;
|
std::unordered_map<std::string, Argument> kwargs;
|
||||||
@@ -154,7 +154,10 @@ public:
|
|||||||
args.push_back(parseArgument());
|
args.push_back(parseArgument());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Command(name, std::move(args), std::move(kwargs), executor);
|
return Command(
|
||||||
|
name, std::move(args), std::move(kwargs),
|
||||||
|
std::string(description), executor
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline parsing_error argumentError(
|
inline parsing_error argumentError(
|
||||||
@@ -368,18 +371,24 @@ public:
|
|||||||
while (auto arg = command->getArgument(arg_index++)) {
|
while (auto arg = command->getArgument(arg_index++)) {
|
||||||
if (!arg->optional) {
|
if (!arg->optional) {
|
||||||
throw error("missing argument "+util::quote(arg->name));
|
throw error("missing argument "+util::quote(arg->name));
|
||||||
|
} else {
|
||||||
|
args->put(arg->def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Prompt {command, args, kwargs};
|
return Prompt {command, args, kwargs};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Command Command::create(std::string_view scheme, executor_func executor) {
|
Command Command::create(std::string_view scheme, std::string_view description, executor_func executor) {
|
||||||
return CommandParser("<string>", scheme).parseScheme(executor);
|
return CommandParser("<string>", scheme).parseScheme(executor, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandsRepository::add(std::string_view scheme, executor_func executor) {
|
void CommandsRepository::add(
|
||||||
Command command = Command::create(scheme, executor);
|
std::string_view scheme,
|
||||||
|
std::string_view description,
|
||||||
|
executor_func executor
|
||||||
|
) {
|
||||||
|
Command command = Command::create(scheme, description, executor);
|
||||||
commands[command.getName()] = command;
|
commands[command.getName()] = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,17 @@ namespace cmd {
|
|||||||
number, integer, enumvalue, selector, string
|
number, integer, enumvalue, selector, string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::string argtype_name(ArgType type) {
|
||||||
|
switch (type) {
|
||||||
|
case ArgType::number: return "number";
|
||||||
|
case ArgType::integer: return "integer";
|
||||||
|
case ArgType::enumvalue: return "enumeration";
|
||||||
|
case ArgType::selector: return "selector";
|
||||||
|
case ArgType::string: return "string";
|
||||||
|
default: return "<unknown>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Argument {
|
struct Argument {
|
||||||
std::string name;
|
std::string name;
|
||||||
ArgType type;
|
ArgType type;
|
||||||
@@ -41,6 +52,7 @@ namespace cmd {
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::vector<Argument> args;
|
std::vector<Argument> args;
|
||||||
std::unordered_map<std::string, Argument> kwargs;
|
std::unordered_map<std::string, Argument> kwargs;
|
||||||
|
std::string description;
|
||||||
executor_func executor;
|
executor_func executor;
|
||||||
public:
|
public:
|
||||||
Command() {}
|
Command() {}
|
||||||
@@ -49,10 +61,12 @@ namespace cmd {
|
|||||||
std::string name,
|
std::string name,
|
||||||
std::vector<Argument> args,
|
std::vector<Argument> args,
|
||||||
std::unordered_map<std::string, Argument> kwargs,
|
std::unordered_map<std::string, Argument> kwargs,
|
||||||
|
std::string description,
|
||||||
executor_func executor
|
executor_func executor
|
||||||
) : name(name),
|
) : name(name),
|
||||||
args(std::move(args)),
|
args(std::move(args)),
|
||||||
kwargs(std::move(kwargs)),
|
kwargs(std::move(kwargs)),
|
||||||
|
description(description),
|
||||||
executor(executor) {}
|
executor(executor) {}
|
||||||
|
|
||||||
Argument* getArgument(size_t index) {
|
Argument* getArgument(size_t index) {
|
||||||
@@ -77,14 +91,38 @@ namespace cmd {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Command create(std::string_view scheme, executor_func);
|
const std::vector<Argument>& getArgs() const {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, Argument>& getKwArgs() const {
|
||||||
|
return kwargs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& getDescription() const {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Command create(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string_view description,
|
||||||
|
executor_func
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandsRepository {
|
class CommandsRepository {
|
||||||
std::unordered_map<std::string, Command> commands;
|
std::unordered_map<std::string, Command> commands;
|
||||||
public:
|
public:
|
||||||
void add(std::string_view scheme, executor_func);
|
void add(
|
||||||
|
std::string_view scheme,
|
||||||
|
std::string_view description,
|
||||||
|
executor_func
|
||||||
|
);
|
||||||
Command* get(const std::string& name);
|
Command* get(const std::string& name);
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, Command> getCommands() const {
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandsInterpreter {
|
class CommandsInterpreter {
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ using namespace scripting;
|
|||||||
|
|
||||||
static int l_add_command(lua_State* L) {
|
static int l_add_command(lua_State* L) {
|
||||||
auto scheme = lua_tostring(L, 1);
|
auto scheme = lua_tostring(L, 1);
|
||||||
lua_pushvalue(L, 2);
|
auto description = lua_tostring(L, 2);
|
||||||
|
lua_pushvalue(L, 3);
|
||||||
auto func = state->createLambda();
|
auto func = state->createLambda();
|
||||||
try {
|
try {
|
||||||
engine->getCommandsInterpreter()->getRepository()->add(
|
engine->getCommandsInterpreter()->getRepository()->add(
|
||||||
scheme, [func](auto, auto args, auto kwargs) {
|
scheme, description, [func](auto, auto args, auto kwargs) {
|
||||||
return func({args, kwargs});
|
return func({args, kwargs});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -43,9 +44,74 @@ static int l_set(lua_State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_get_commands_list(lua_State* L) {
|
||||||
|
auto interpreter = engine->getCommandsInterpreter();
|
||||||
|
auto repo = interpreter->getRepository();
|
||||||
|
const auto& commands = repo->getCommands();
|
||||||
|
|
||||||
|
lua_createtable(L, commands.size(), 0);
|
||||||
|
size_t index = 1;
|
||||||
|
for (const auto& entry : commands) {
|
||||||
|
lua_pushstring(L, entry.first.c_str());
|
||||||
|
lua_rawseti(L, -2, index++);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_get_command_info(lua_State* L) {
|
||||||
|
auto name = lua_tostring(L, 1);
|
||||||
|
auto interpreter = engine->getCommandsInterpreter();
|
||||||
|
auto repo = interpreter->getRepository();
|
||||||
|
auto command = repo->get(name);
|
||||||
|
const auto& args = command->getArgs();
|
||||||
|
const auto& kwargs = command->getKwArgs();
|
||||||
|
|
||||||
|
lua_createtable(L, 0, 4);
|
||||||
|
|
||||||
|
lua_pushstring(L, name);
|
||||||
|
lua_setfield(L, -2, "name");
|
||||||
|
|
||||||
|
lua_pushstring(L, command->getDescription().c_str());
|
||||||
|
lua_setfield(L, -2, "description");
|
||||||
|
|
||||||
|
lua_createtable(L, args.size(), 0);
|
||||||
|
for (size_t i = 0; i < args.size(); i++) {
|
||||||
|
auto& arg = args.at(i);
|
||||||
|
lua_createtable(L, 0, 2);
|
||||||
|
|
||||||
|
lua_pushstring(L, arg.name.c_str());
|
||||||
|
lua_setfield(L, -2, "name");
|
||||||
|
|
||||||
|
lua_pushstring(L, cmd::argtype_name(arg.type).c_str());
|
||||||
|
lua_setfield(L, -2, "type");
|
||||||
|
|
||||||
|
if (arg.optional) {
|
||||||
|
lua_pushboolean(L, true);
|
||||||
|
lua_setfield(L, -2, "optional");
|
||||||
|
}
|
||||||
|
lua_rawseti(L, -2, i+1);
|
||||||
|
}
|
||||||
|
lua_setfield(L, -2, "args");
|
||||||
|
|
||||||
|
lua_createtable(L, 0, kwargs.size());
|
||||||
|
for (auto& entry : kwargs) {
|
||||||
|
auto& arg = entry.second;
|
||||||
|
lua_createtable(L, 0, 1);
|
||||||
|
|
||||||
|
lua_pushstring(L, cmd::argtype_name(arg.type).c_str());
|
||||||
|
lua_setfield(L, -2, "type");
|
||||||
|
|
||||||
|
lua_setfield(L, -2, arg.name.c_str());
|
||||||
|
}
|
||||||
|
lua_setfield(L, -2, "kwargs");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
const luaL_Reg consolelib [] = {
|
const luaL_Reg consolelib [] = {
|
||||||
{"add_command", lua_wrap_errors<l_add_command>},
|
{"add_command", lua_wrap_errors<l_add_command>},
|
||||||
{"execute", lua_wrap_errors<l_execute>},
|
{"execute", lua_wrap_errors<l_execute>},
|
||||||
{"set", lua_wrap_errors<l_set>},
|
{"set", lua_wrap_errors<l_set>},
|
||||||
|
{"get_commands_list", lua_wrap_errors<l_get_commands_list>},
|
||||||
|
{"get_command_info", lua_wrap_errors<l_get_command_info>},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user