feat(help): improve TLDR/help handling for help context commands
- Added `from_help` flag to `get_command()` to allow help rendering without full CLI execution flow. - Updated `_render_help()` to pass `from_help=True` when fetching commands. - Enhanced TLDR parsing: - Allow TLDR flag to be processed and retained when running inside a help command (`_is_help_command=True`). - Skip removing `"tldr"` from results in help context to preserve intended behavior. - Ensure TLDR args are still marked consumed to maintain state consistency. - Simplified required argument validation to skip both `help` and `tldr` without special action checks. - Adjusted `parse_args_split()` to include `tldr` values in help commands while skipping them for normal commands. - Expanded `infer_args_from_func()` docstring with supported features and parameter handling details. - Bumped version to 0.1.84.
This commit is contained in:
@ -411,7 +411,7 @@ class Falyx:
|
|||||||
self.console.print(f"[bold]tip:[/bold] {self.get_tip()}")
|
self.console.print(f"[bold]tip:[/bold] {self.get_tip()}")
|
||||||
return None
|
return None
|
||||||
if key:
|
if key:
|
||||||
_, command, args, kwargs = await self.get_command(key)
|
_, command, args, kwargs = await self.get_command(key, from_help=True)
|
||||||
if command and tldr and command.arg_parser:
|
if command and tldr and command.arg_parser:
|
||||||
command.arg_parser.render_tldr()
|
command.arg_parser.render_tldr()
|
||||||
self.console.print(f"[bold]tip:[/bold] {self.get_tip()}")
|
self.console.print(f"[bold]tip:[/bold] {self.get_tip()}")
|
||||||
@ -941,7 +941,7 @@ class Falyx:
|
|||||||
return False, input_str.strip()
|
return False, input_str.strip()
|
||||||
|
|
||||||
async def get_command(
|
async def get_command(
|
||||||
self, raw_choices: str, from_validate=False
|
self, raw_choices: str, from_validate=False, from_help=False
|
||||||
) -> tuple[bool, Command | None, tuple, dict[str, Any]]:
|
) -> tuple[bool, Command | None, tuple, dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Returns the selected command based on user input.
|
Returns the selected command based on user input.
|
||||||
@ -982,7 +982,7 @@ class Falyx:
|
|||||||
logger.info("Command '%s' selected.", run_command.key)
|
logger.info("Command '%s' selected.", run_command.key)
|
||||||
if is_preview:
|
if is_preview:
|
||||||
return True, run_command, args, kwargs
|
return True, run_command, args, kwargs
|
||||||
elif self.is_cli_mode:
|
elif self.is_cli_mode or from_help:
|
||||||
return False, run_command, args, kwargs
|
return False, run_command, args, kwargs
|
||||||
try:
|
try:
|
||||||
args, kwargs = await run_command.parse_args(input_args, from_validate)
|
args, kwargs = await run_command.parse_args(input_args, from_validate)
|
||||||
|
@ -913,10 +913,18 @@ class CommandArgumentParser:
|
|||||||
arg_states[spec.dest].set_consumed()
|
arg_states[spec.dest].set_consumed()
|
||||||
raise HelpSignal()
|
raise HelpSignal()
|
||||||
elif action == ArgumentAction.TLDR:
|
elif action == ArgumentAction.TLDR:
|
||||||
if not from_validate:
|
if self._is_help_command:
|
||||||
|
result[spec.dest] = True
|
||||||
|
arg_states[spec.dest].set_consumed()
|
||||||
|
consumed_indices.add(index)
|
||||||
|
index += 1
|
||||||
|
elif not from_validate:
|
||||||
self.render_tldr()
|
self.render_tldr()
|
||||||
arg_states[spec.dest].set_consumed()
|
arg_states[spec.dest].set_consumed()
|
||||||
raise HelpSignal()
|
raise HelpSignal()
|
||||||
|
else:
|
||||||
|
arg_states[spec.dest].set_consumed()
|
||||||
|
raise HelpSignal()
|
||||||
elif action == ArgumentAction.ACTION:
|
elif action == ArgumentAction.ACTION:
|
||||||
assert isinstance(
|
assert isinstance(
|
||||||
spec.resolver, BaseAction
|
spec.resolver, BaseAction
|
||||||
@ -1129,11 +1137,7 @@ class CommandArgumentParser:
|
|||||||
|
|
||||||
# Required validation
|
# Required validation
|
||||||
for spec in self._arguments:
|
for spec in self._arguments:
|
||||||
if (
|
if spec.dest == "help" or spec.dest == "tldr":
|
||||||
spec.dest == "help"
|
|
||||||
or spec.dest == "tldr"
|
|
||||||
and spec.action == ArgumentAction.TLDR
|
|
||||||
):
|
|
||||||
continue
|
continue
|
||||||
if spec.required and not result.get(spec.dest):
|
if spec.required and not result.get(spec.dest):
|
||||||
help_text = f" help: {spec.help}" if spec.help else ""
|
help_text = f" help: {spec.help}" if spec.help else ""
|
||||||
@ -1184,7 +1188,8 @@ class CommandArgumentParser:
|
|||||||
)
|
)
|
||||||
|
|
||||||
result.pop("help", None)
|
result.pop("help", None)
|
||||||
result.pop("tldr", None)
|
if not self._is_help_command:
|
||||||
|
result.pop("tldr", None)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def parse_args_split(
|
async def parse_args_split(
|
||||||
@ -1202,7 +1207,9 @@ class CommandArgumentParser:
|
|||||||
args_list = []
|
args_list = []
|
||||||
kwargs_dict = {}
|
kwargs_dict = {}
|
||||||
for arg in self._arguments:
|
for arg in self._arguments:
|
||||||
if arg.dest in ("help", "tldr"):
|
if arg.dest == "help":
|
||||||
|
continue
|
||||||
|
if arg.dest == "tldr" and not self._is_help_command:
|
||||||
continue
|
continue
|
||||||
if arg.positional:
|
if arg.positional:
|
||||||
args_list.append(parsed[arg.dest])
|
args_list.append(parsed[arg.dest])
|
||||||
|
@ -26,6 +26,18 @@ def infer_args_from_func(
|
|||||||
This utility inspects the parameters of a function and returns a list of dictionaries,
|
This utility inspects the parameters of a function and returns a list of dictionaries,
|
||||||
each of which can be passed to `CommandArgumentParser.add_argument()`.
|
each of which can be passed to `CommandArgumentParser.add_argument()`.
|
||||||
|
|
||||||
|
It supports:
|
||||||
|
- Positional and keyword arguments
|
||||||
|
- Type hints for argument types
|
||||||
|
- Default values
|
||||||
|
- Required vs optional arguments
|
||||||
|
- Custom help text, choices, and suggestions via metadata
|
||||||
|
|
||||||
|
Note:
|
||||||
|
- Only parameters with kind `POSITIONAL_ONLY`, `POSITIONAL_OR_KEYWORD`, or
|
||||||
|
`KEYWORD_ONLY` are considered.
|
||||||
|
- Parameters with kind `VAR_POSITIONAL` or `VAR_KEYWORD` are ignored.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
func (Callable | None): The function to inspect.
|
func (Callable | None): The function to inspect.
|
||||||
arg_metadata (dict | None): Optional metadata overrides for help text, type hints,
|
arg_metadata (dict | None): Optional metadata overrides for help text, type hints,
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "0.1.83"
|
__version__ = "0.1.84"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "falyx"
|
name = "falyx"
|
||||||
version = "0.1.83"
|
version = "0.1.84"
|
||||||
description = "Reliable and introspectable async CLI action framework."
|
description = "Reliable and introspectable async CLI action framework."
|
||||||
authors = ["Roland Thomas Jr <roland@rtj.dev>"]
|
authors = ["Roland Thomas Jr <roland@rtj.dev>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
Reference in New Issue
Block a user