Add fancy argument parsing
This commit is contained in:
parent
135640ca44
commit
24128a460a
3 changed files with 95 additions and 2 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
## Next version
|
||||
|
||||
- add fancy argument parsing
|
||||
- add login and logout command to room
|
||||
- add pm command to room
|
||||
- add cookie support
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ i. e. the text between the end of the "!echo" and the end of the whole message.
|
|||
## TODOs
|
||||
|
||||
- [ ] document yaboli (markdown files in a "docs" folder?)
|
||||
- [ ] fancy argument parsing
|
||||
- [ ] document new classes (docstrings, maybe comments)
|
||||
- [ ] write examples
|
||||
- [ ] make yaboli package play nice with mypy
|
||||
|
|
@ -69,3 +68,4 @@ i. e. the text between the end of the "!echo" and the end of the whole message.
|
|||
- [x] implement !restart
|
||||
- [x] write project readme
|
||||
- [x] cookie support
|
||||
- [x] fancy argument parsing
|
||||
|
|
|
|||
|
|
@ -23,9 +23,70 @@ __all__ = ["FancyArgs", "ArgumentData", "SpecificArgumentData", "CommandData",
|
|||
"SpecificCommandFunction", "SpecificCommand"]
|
||||
|
||||
class FancyArgs(NamedTuple):
|
||||
"""
|
||||
The fancy argument parser supports arguments of the following formats:
|
||||
|
||||
|
||||
FLAGS:
|
||||
|
||||
These are one or more characters preceded by a single dash. Examples:
|
||||
|
||||
-a, -fghf, -vv
|
||||
|
||||
The fancy argument parser counts how often each character (also called
|
||||
flag) appears. Each flag that appears once or more gets an entry in the
|
||||
"flags" dict of the form: flags[flag] = amount
|
||||
|
||||
Exception: A single dash ("-") is interpreted as a positional argument.
|
||||
|
||||
|
||||
OPTIONAL:
|
||||
|
||||
These are arguments of the form --<name> or --<name>=<value>, where <name>
|
||||
is the name of the optional argument and <value> is its (optional) value.
|
||||
|
||||
Due to this syntax, the <name> may not include any "=" signs.
|
||||
|
||||
The optional arguments are collected in a dict of the form:
|
||||
|
||||
optional[name] = value or None
|
||||
|
||||
If the optional argument included a "=" after the name, but no further
|
||||
characters, its value is the empty string. If it didn't include a "=" after
|
||||
the name, its value is None.
|
||||
|
||||
If more than one optional argument appears with the same name, the last
|
||||
argument's value is kept and all previous values discarded.
|
||||
|
||||
|
||||
POSITIONAL:
|
||||
|
||||
Positional arguments are all arguments that don't start with "-" or "--".
|
||||
They are compiled in a list and ordered in the same order they appeared in
|
||||
after the command.
|
||||
|
||||
|
||||
RAW:
|
||||
|
||||
At any time, a single "--" argument may be inserted. This separates the
|
||||
positional and optional arguments and the flags from the raw arguments. All
|
||||
arguments after the "--" are interpreted as raw arguments, even flags,
|
||||
optional arguments and further "--"s.
|
||||
|
||||
For example, consider the following arguments:
|
||||
|
||||
ab -cd -c --ef=g --h i -- j --klm -nop -- qr
|
||||
|
||||
positional: ["ab", "i"]
|
||||
optional: {"ef": "g", "h": None}
|
||||
flags: {"c": 2, "d": 1}
|
||||
raw: ["j", "--klm", "-nop", "--", "qr"]
|
||||
"""
|
||||
|
||||
positional: List[str]
|
||||
optional: Dict[str, Optional[str]]
|
||||
flags: Dict[str, int]
|
||||
raw: List[str]
|
||||
|
||||
class ArgumentData:
|
||||
def __init__(self, raw: str) -> None:
|
||||
|
|
@ -94,7 +155,38 @@ class ArgumentData:
|
|||
return text.split()
|
||||
|
||||
def _parse_fancy(self, args: List[str]) -> FancyArgs:
|
||||
raise NotImplementedError # TODO
|
||||
positional: List[str] = []
|
||||
optional: Dict[str, Optional[str]] = {}
|
||||
flags: Dict[str, int] = {}
|
||||
raw: List[str] = []
|
||||
|
||||
is_raw = False
|
||||
|
||||
for arg in args:
|
||||
# raw arguments
|
||||
if is_raw:
|
||||
raw.append(arg)
|
||||
# raw arguments separator
|
||||
elif arg == "--":
|
||||
is_raw = True
|
||||
# optional arguments
|
||||
elif arg[:2] == "--":
|
||||
split = arg[2:].split("=", maxsplit=1)
|
||||
name = split[0]
|
||||
value = split[1] if len(split) == 2 else None
|
||||
optional[name] = value
|
||||
# the "-" exception
|
||||
elif arg == "-":
|
||||
positional.append(arg)
|
||||
# flags
|
||||
elif arg[:1] == "-":
|
||||
for char in arg[1:]:
|
||||
flags[char] = flags.get(char, 0) + 1
|
||||
# positional arguments
|
||||
else:
|
||||
positional.append(arg)
|
||||
|
||||
return FancyArgs(positional, optional, flags, raw)
|
||||
|
||||
@property
|
||||
def raw(self) -> str:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue