WorldEdit
WorldEdit copied to clipboard
Create a command argument parser
Currently every command has to be manually parsed to check if all the parameters are correct and the extract the values from them. If we'd create some kind of parser that would allow us to do this automatically creating new commands would get allot easier. I had something like this in mind:
function HandleCommand(a_Split, a_Player)
-- //command <radius> <block> [hollow]
local parser, errorMsg = cCommandParser:new("<CommandName> <radius:number> <block:block> [hollow:bool]")
:Parse(a_Split)
if (not parser) then
a_Player:SendMessage(cChatColor.Rose .. errorMsg)
return true
end
DoSomething(parser.radius, parser.block, parser.hollow)
return true;
end
Any thoughts?
It might be easier to specify the parameters in a Lua table, rather than a string:
cCommandParser:new({
{ name = "radius", type = "number"},
{ name = "block", type = "block"},
{ name = "ishollow", type = "bool", optional = true}
})
How about commands with multiple syntaxes?
Yeah, that's probably nicer. If multiple syntaxes are allowed we could provide an array of command objects. Handling whatever the parser returns might be a little harder to do nicely though. Are there even any commands with multiple syntaxes?
Perhaps instead of providing a type for the argument we provide a function. I could for example provide the GetBlockDst
function which chooses the right BlockTypeSource
depending on the argument.
I'm a bit worried that this is an "inner platform"...
You mean the whole idea of the command parser?
@madmaxoft I thought about that as well. When this feature makes it easier to create plugins, then it should be part of the server and exported as an API
I have an idea on how to do this which is actually pretty simple. I'd like to try it out first, but I think it could work.
This sounds very interesting...
I'm afraid the user won't notice allot, but it makes creating new commands a little easier and nicer.
Agreed, that's exactly what makes it sound interesting.
It seems to be working. A JSON dump of the result gives this:
{
"Arguments" :
{
"block" :
{
"m_BlockTable" :
[
{
"BlockMeta" : 0,
"BlockType" : 12,
"Chance" : 0.5
},
{
"BlockMeta" : 0,
"BlockType" : 8,
"Chance" : 1
}
]
},
"depth" : 2,
"radius" : 20
},
"Flags" :
{
"fancyname" : false,
"hollow" : true
}
}
While this code is used in the command handler:
local success, cCommandParser:new(2)
:Arguments({
{ name = "block", extractor = Extractors.Block},
{ name = "radius", extractor = Extractors.Number},
{ name = "depth", extractor = Extractors.Number, optional = true },
})
:Flags({
{ name = 'hollow', character = 'h' },
{ name = 'fancyname', character = 'o' }
})
:Parse(arguments, player)
The input of the user looks like this:
//fill -h sand,water 20 2
The overal parser is a little under 200 lines, but I do have to include a few things.
I uploaded my initial version here: https://github.com/cuberite/WorldEdit/tree/CommandParser
Any thoughts?
It'd be nice if the parsed usage was documented somewhere in the parser's implementation file. An example usage, input and output should be given, too.