Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a command argument parser #117

Open
NiLSPACE opened this issue Feb 26, 2017 · 14 comments
Open

Create a command argument parser #117

NiLSPACE opened this issue Feb 26, 2017 · 14 comments

Comments

@NiLSPACE
Copy link
Member

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?

@madmaxoft
Copy link
Member

madmaxoft commented Feb 26, 2017

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?

@NiLSPACE
Copy link
Member Author

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?

@NiLSPACE
Copy link
Member Author

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.

@madmaxoft
Copy link
Member

I'm a bit worried that this is an "inner platform"...

@NiLSPACE
Copy link
Member Author

You mean the whole idea of the command parser?

@sphinxc0re
Copy link

@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

@NiLSPACE
Copy link
Member Author

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.

@HelenaKitty
Copy link

This sounds very interesting...

@NiLSPACE
Copy link
Member Author

I'm afraid the user won't notice allot, but it makes creating new commands a little easier and nicer.

@HelenaKitty
Copy link

Agreed, that's exactly what makes it sound interesting.

@NiLSPACE
Copy link
Member Author

NiLSPACE commented Feb 27, 2017

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.

@NiLSPACE
Copy link
Member Author

I uploaded my initial version here: https://github.com/cuberite/WorldEdit/tree/CommandParser

@NiLSPACE
Copy link
Member Author

NiLSPACE commented Mar 2, 2017

Any thoughts?

@madmaxoft
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants