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

Add alias support and update help func output to include it. #23

Merged
merged 2 commits into from
Apr 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ fn print_information(command: CommandArc, args: List[String]) -> None:


fn get_cat_fact(command: CommandArc, args: List[String]) -> Error:
var flags = command[].get_all_flags()[]
var flags = command[].flags[]
var lover = flags.get_as_bool("lover")
if lover and lover.value():
if lover and lover.value()[]:
print("Hello fellow cat lover!")

try:
Expand All @@ -54,7 +54,7 @@ fn get_cat_fact(command: CommandArc, args: List[String]) -> Error:
if not count:
return Error("Count flag was not found.")
var body = response.json()
for i in range(count.value()):
for i in range(count.value()[]):
print(body[i]["text"])
else:
return Error("Request failed!")
Expand Down Expand Up @@ -98,8 +98,8 @@ fn init() -> None:
description="Get some cat facts!",
erroring_run=get_cat_fact,
)
cat_command.flags.add_int_flag[name="count", shorthand="c", usage="Number of facts to get."]()
cat_command.flags.add_bool_flag[name="lover", shorthand="l", usage="Are you a cat lover?"]()
cat_command.add_int_flag(name="count", shorthand="c", usage="Number of facts to get.")
cat_command.add_bool_flag(name="lover", shorthand="l", usage="Are you a cat lover?")

var dog_command = Command(
name="dog",
Expand All @@ -116,7 +116,6 @@ fn init() -> None:
fn main() -> None:
init()


```

Start by navigating to the `nested` example directory.
Expand Down Expand Up @@ -201,7 +200,11 @@ Usage information will be printed the console by passing the `--help` flag.

- Add find suggestion logic to `Command` struct.
- Enable required flags.
- Add flag groups and mutually exclusive flags.
- Add subcommand groups.
- Enable usage function to return the results of a usage function upon calling wrong functions or commands.
- Replace print usage with writers to enable stdout/stderr/file writing.
- Update default help command to improve available commands and flags section.

### Improvements

Expand Down
Empty file added examples/aliases/__init__.mojo
Empty file.
30 changes: 30 additions & 0 deletions examples/aliases/root.mojo
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from memory._arc import Arc
from prism import Flag, Command, CommandArc
from prism.vector import to_string


fn test(command: CommandArc, args: List[String]) -> None:
print("Pass tool, object, or thing as a subcommand!")


fn tool_func(command: CommandArc, args: List[String]) -> None:
print("My tool!")


fn init() -> None:
var root_command = Command(
name="my",
description="This is a dummy command!",
run=test,
)

var tool_command = Command(
name="tool", description="This is a dummy command!", run=tool_func, aliases=List[String]("object", "thing")
)

root_command.add_command(tool_command)
root_command.execute()


fn main() -> None:
init()
49 changes: 33 additions & 16 deletions prism/command.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,32 @@ fn get_args_as_list() -> List[String]:

fn default_help(command: Arc[Command]) -> String:
"""Prints the help information for the command."""
var cmd = command[]
var builder = StringBuilder()
_ = builder.write_string(cmd.description)
_ = builder.write_string("\n\n")
_ = builder.write_string(command[].description)

if command[].aliases:
_ = builder.write_string("\n\nAliases:")
_ = builder.write_string(sprintf("\n %s", to_string(command[].aliases)))

# Build usage statement arguments depending on the command's children and flags.
var full_command = cmd._full_command()
_ = builder.write_string(sprintf("Usage:\n %s%s", full_command, String(" [args]")))
if len(cmd.children) > 0:
var full_command = command[]._full_command()
_ = builder.write_string(sprintf("\n\nUsage:\n %s%s", full_command, String(" [args]")))
if len(command[].children) > 0:
_ = builder.write_string(" [command]")
if len(cmd.flags[]) > 0:
if len(command[].flags[]) > 0:
_ = builder.write_string(" [flags]")

_ = builder.write_string("\n\nAvailable commands:\n")
for child in cmd.children:
_ = builder.write_string(sprintf(" %s\n", str(child[][])))
if command[].children:
_ = builder.write_string("\n\nAvailable commands:\n")
for child in command[].children:
_ = builder.write_string(sprintf(" %s\n", str(child[][])))

_ = builder.write_string("\nAvailable flags:\n")
for flag in cmd.flag_list():
_ = builder.write_string(sprintf(" -%s, --%s %s\n", flag[][].shorthand, flag[][].name, flag[][].usage))
if command[].flag_list():
_ = builder.write_string("\n\nAvailable flags:\n")
for flag in command[].flag_list():
_ = builder.write_string(sprintf(" -%s, --%s %s\n", flag[][].shorthand, flag[][].name, flag[][].usage))

_ = builder.write_string(sprintf('Use "%s [command] --help" for more information about a command.', full_command))
_ = builder.write_string(sprintf('\nUse "%s [command] --help" for more information about a command.', full_command))
return str(builder)


Expand All @@ -70,7 +74,7 @@ fn parse_command_from_args(start: Command) -> (Command, List[String]):

for arg in args:
for command_ref in children:
if command_ref[][].name == arg[]:
if command_ref[][].name == arg[] or contains(command_ref[][].aliases, arg[]):
command = command_ref[][]
children = command.children
leftover_args_start_index += 1
Expand Down Expand Up @@ -100,12 +104,19 @@ struct Command(CollectionElement):
erroring_run: The function to run when the command is executed that returns an error.
erroring_pre_run: The function to run before the command is executed that returns an error.
erroring_post_run: The function to run after the command is executed that returns an error.
persisting_pre_run: The function to run before the command is executed. This persists to children.
persisting_post_run: The function to run after the command is executed. This persists to children.
persisting_erroring_pre_run: The function to run before the command is executed that returns an error. This persists to children.
persisting_erroring_post_run: The function to run after the command is executed that returns an error. This persists to children.
help: The function to generate help text for the command.
"""

var name: String
var description: String

# Aliases that can be used instead of the first word in name.
var aliases: List[String]

# Generates help text.
var help: HelpFunction

Expand Down Expand Up @@ -145,6 +156,7 @@ struct Command(CollectionElement):
inout self,
name: String,
description: String,
aliases: List[String] = List[String](),
valid_args: List[String] = List[String](),
run: Optional[CommandFunction] = None,
pre_run: Optional[CommandFunction] = None,
Expand All @@ -163,6 +175,7 @@ struct Command(CollectionElement):

self.name = name
self.description = description
self.aliases = aliases

self.help = help

Expand Down Expand Up @@ -200,6 +213,7 @@ struct Command(CollectionElement):
name: String,
description: String,
arg_validator: ArgValidator,
aliases: List[String] = List[String](),
valid_args: List[String] = List[String](),
run: Optional[CommandFunction] = None,
pre_run: Optional[CommandFunction] = None,
Expand All @@ -218,6 +232,7 @@ struct Command(CollectionElement):

self.name = name
self.description = description
self.aliases = aliases

self.help = help

Expand Down Expand Up @@ -250,6 +265,7 @@ struct Command(CollectionElement):
fn __copyinit__(inout self, existing: Self):
self.name = existing.name
self.description = existing.description
self.aliases = existing.aliases

self.help = existing.help

Expand Down Expand Up @@ -279,6 +295,7 @@ struct Command(CollectionElement):
fn __moveinit__(inout self, owned existing: Self):
self.name = existing.name^
self.description = existing.description^
self.aliases = existing.aliases^

self.help = existing.help

Expand Down Expand Up @@ -306,7 +323,7 @@ struct Command(CollectionElement):
self.parent = existing.parent^

fn __str__(self) -> String:
return "(Name: " + self.name + ", Description: " + self.description + ")"
return sprintf("(Name: %s, Description: %s)", self.name, self.description)

fn __repr__(inout self) -> String:
var parent_name: String = ""
Expand Down
2 changes: 2 additions & 0 deletions run_examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mkdir ./temp
mojo package prism -I ./external -o ./temp/prism.mojopkg

echo -e "Building binaries for all examples...\n"
mojo build examples/aliases/root.mojo -o temp/aliases
mojo build examples/hello_world/root.mojo -o temp/hello_world
mojo build examples/nested/nested.mojo -o temp/nested
mojo build examples/printer/printer.mojo -o temp/printer
Expand All @@ -15,6 +16,7 @@ mkdir -p temp/examples/read_csv/ && cp examples/read_csv/file.csv temp/examples/

echo -e "Executing examples...\n"
cd temp
./aliases my thing
./hello_world say hello
./nested get cat --count 5 -l
./printer "sample-text" --formatting=underline
Expand Down
Loading