falyx 0.1.58__py3-none-any.whl → 0.1.59__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- falyx/action/confirm_action.py +13 -8
- falyx/action/signal_action.py +1 -1
- falyx/bottom_bar.py +1 -0
- falyx/falyx.py +1 -3
- falyx/parser/parsers.py +105 -2
- falyx/validators.py +9 -6
- falyx/version.py +1 -1
- {falyx-0.1.58.dist-info → falyx-0.1.59.dist-info}/METADATA +1 -1
- {falyx-0.1.58.dist-info → falyx-0.1.59.dist-info}/RECORD +12 -12
- {falyx-0.1.58.dist-info → falyx-0.1.59.dist-info}/WHEEL +1 -1
- {falyx-0.1.58.dist-info → falyx-0.1.59.dist-info}/LICENSE +0 -0
- {falyx-0.1.58.dist-info → falyx-0.1.59.dist-info}/entry_points.txt +0 -0
falyx/action/confirm_action.py
CHANGED
@@ -56,13 +56,14 @@ class ConfirmAction(BaseAction):
|
|
56
56
|
prompt_session (PromptSession | None): The session to use for input.
|
57
57
|
confirm (bool): Whether to prompt the user for confirmation.
|
58
58
|
word (str): The word to type for TYPE_WORD confirmation.
|
59
|
-
return_last_result (bool): Whether to return the last result of the action
|
59
|
+
return_last_result (bool): Whether to return the last result of the action
|
60
|
+
instead of a boolean.
|
60
61
|
"""
|
61
62
|
|
62
63
|
def __init__(
|
63
64
|
self,
|
64
65
|
name: str,
|
65
|
-
message: str = "
|
66
|
+
message: str = "Confirm?",
|
66
67
|
confirm_type: ConfirmType | str = ConfirmType.YES_NO,
|
67
68
|
prompt_session: PromptSession | None = None,
|
68
69
|
confirm: bool = True,
|
@@ -114,16 +115,19 @@ class ConfirmAction(BaseAction):
|
|
114
115
|
session=self.prompt_session,
|
115
116
|
)
|
116
117
|
case ConfirmType.YES_NO_CANCEL:
|
118
|
+
error_message = "Enter 'Y', 'y' to confirm, 'N', 'n' to decline, or 'C', 'c' to abort."
|
117
119
|
answer = await self.prompt_session.prompt_async(
|
118
|
-
f"❓ {self.message}
|
119
|
-
validator=words_validator(
|
120
|
+
f"❓ {self.message} [Y]es, [N]o, or [C]ancel to abort > ",
|
121
|
+
validator=words_validator(
|
122
|
+
["Y", "N", "C"], error_message=error_message
|
123
|
+
),
|
120
124
|
)
|
121
125
|
if answer.upper() == "C":
|
122
126
|
raise CancelSignal(f"Action '{self.name}' was cancelled by the user.")
|
123
127
|
return answer.upper() == "Y"
|
124
128
|
case ConfirmType.TYPE_WORD:
|
125
129
|
answer = await self.prompt_session.prompt_async(
|
126
|
-
f"❓ {self.message}
|
130
|
+
f"❓ {self.message} [{self.word}] to confirm or [N/n] > ",
|
127
131
|
validator=word_validator(self.word),
|
128
132
|
)
|
129
133
|
return answer.upper().strip() != "N"
|
@@ -138,9 +142,10 @@ class ConfirmAction(BaseAction):
|
|
138
142
|
raise CancelSignal(f"Action '{self.name}' was cancelled by the user.")
|
139
143
|
return answer
|
140
144
|
case ConfirmType.OK_CANCEL:
|
145
|
+
error_message = "Enter 'O', 'o' to confirm or 'C', 'c' to abort."
|
141
146
|
answer = await self.prompt_session.prompt_async(
|
142
|
-
f"❓ {self.message}
|
143
|
-
validator=words_validator(["O", "C"]),
|
147
|
+
f"❓ {self.message} [O]k to confirm, [C]ancel to abort > ",
|
148
|
+
validator=words_validator(["O", "C"], error_message=error_message),
|
144
149
|
)
|
145
150
|
if answer.upper() == "C":
|
146
151
|
raise CancelSignal(f"Action '{self.name}' was cancelled by the user.")
|
@@ -213,5 +218,5 @@ class ConfirmAction(BaseAction):
|
|
213
218
|
def __str__(self) -> str:
|
214
219
|
return (
|
215
220
|
f"ConfirmAction(name={self.name}, message={self.message}, "
|
216
|
-
f"confirm_type={self.confirm_type})"
|
221
|
+
f"confirm_type={self.confirm_type}, return_last_result={self.return_last_result})"
|
217
222
|
)
|
falyx/action/signal_action.py
CHANGED
@@ -14,7 +14,7 @@ class SignalAction(Action):
|
|
14
14
|
Useful for exiting a menu, going back, or halting execution gracefully.
|
15
15
|
"""
|
16
16
|
|
17
|
-
def __init__(self, name: str, signal:
|
17
|
+
def __init__(self, name: str, signal: FlowSignal):
|
18
18
|
self.signal = signal
|
19
19
|
super().__init__(name, action=self.raise_signal)
|
20
20
|
|
falyx/bottom_bar.py
CHANGED
@@ -5,6 +5,7 @@ from typing import Any, Callable
|
|
5
5
|
|
6
6
|
from prompt_toolkit.formatted_text import HTML, merge_formatted_text
|
7
7
|
from prompt_toolkit.key_binding import KeyBindings
|
8
|
+
from rich.console import Console
|
8
9
|
|
9
10
|
from falyx.console import console
|
10
11
|
from falyx.options_manager import OptionsManager
|
falyx/falyx.py
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
2
|
-
"""
|
3
|
-
|
4
|
-
Main class for constructing and running Falyx CLI menus.
|
2
|
+
"""Main class for constructing and running Falyx CLI menus.
|
5
3
|
|
6
4
|
Falyx provides a structured, customizable interactive menu system
|
7
5
|
for running commands, actions, and workflows. It supports:
|
falyx/parser/parsers.py
CHANGED
@@ -56,6 +56,39 @@ def get_root_parser(
|
|
56
56
|
allow_abbrev: bool = True,
|
57
57
|
exit_on_error: bool = True,
|
58
58
|
) -> ArgumentParser:
|
59
|
+
"""
|
60
|
+
Construct the root-level ArgumentParser for the Falyx CLI.
|
61
|
+
|
62
|
+
This parser handles global arguments shared across subcommands and can serve
|
63
|
+
as the base parser for the Falyx CLI or standalone applications. It includes
|
64
|
+
options for verbosity, debug logging, and version output.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
prog (str | None): Name of the program (e.g., 'falyx').
|
68
|
+
usage (str | None): Optional custom usage string.
|
69
|
+
description (str | None): Description shown in the CLI help.
|
70
|
+
epilog (str | None): Message displayed at the end of help output.
|
71
|
+
parents (Sequence[ArgumentParser] | None): Optional parent parsers.
|
72
|
+
prefix_chars (str): Characters to denote optional arguments (default: "-").
|
73
|
+
fromfile_prefix_chars (str | None): Prefix to indicate argument file input.
|
74
|
+
argument_default (Any): Global default value for arguments.
|
75
|
+
conflict_handler (str): Strategy to resolve conflicting argument names.
|
76
|
+
add_help (bool): Whether to include help (`-h/--help`) in this parser.
|
77
|
+
allow_abbrev (bool): Allow abbreviated long options.
|
78
|
+
exit_on_error (bool): Exit immediately on error or raise an exception.
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
ArgumentParser: The root parser with global options attached.
|
82
|
+
|
83
|
+
Notes:
|
84
|
+
```
|
85
|
+
Includes the following arguments:
|
86
|
+
--never-prompt : Run in non-interactive mode.
|
87
|
+
-v / --verbose : Enable debug logging.
|
88
|
+
--debug-hooks : Enable hook lifecycle debug logs.
|
89
|
+
--version : Print the Falyx version.
|
90
|
+
```
|
91
|
+
"""
|
59
92
|
parser = ArgumentParser(
|
60
93
|
prog=prog,
|
61
94
|
usage=usage,
|
@@ -92,7 +125,30 @@ def get_subparsers(
|
|
92
125
|
title: str = "Falyx Commands",
|
93
126
|
description: str | None = "Available commands for the Falyx CLI.",
|
94
127
|
) -> _SubParsersAction:
|
95
|
-
"""
|
128
|
+
"""
|
129
|
+
Create and return a subparsers object for registering Falyx CLI subcommands.
|
130
|
+
|
131
|
+
This function adds a `subparsers` block to the given root parser, enabling
|
132
|
+
structured subcommands such as `run`, `run-all`, `preview`, etc.
|
133
|
+
|
134
|
+
Args:
|
135
|
+
parser (ArgumentParser): The root parser to attach the subparsers to.
|
136
|
+
title (str): Title used in help output to group subcommands.
|
137
|
+
description (str | None): Optional text describing the group of subcommands.
|
138
|
+
|
139
|
+
Returns:
|
140
|
+
_SubParsersAction: The subparsers object that can be used to add new CLI subcommands.
|
141
|
+
|
142
|
+
Raises:
|
143
|
+
TypeError: If `parser` is not an instance of `ArgumentParser`.
|
144
|
+
|
145
|
+
Example:
|
146
|
+
```python
|
147
|
+
>>> parser = get_root_parser()
|
148
|
+
>>> subparsers = get_subparsers(parser, title="Available Commands")
|
149
|
+
>>> subparsers.add_parser("run", help="Run a Falyx command")
|
150
|
+
```
|
151
|
+
"""
|
96
152
|
if not isinstance(parser, ArgumentParser):
|
97
153
|
raise TypeError("parser must be an instance of ArgumentParser")
|
98
154
|
subparsers = parser.add_subparsers(
|
@@ -122,7 +178,54 @@ def get_arg_parsers(
|
|
122
178
|
root_parser: ArgumentParser | None = None,
|
123
179
|
subparsers: _SubParsersAction | None = None,
|
124
180
|
) -> FalyxParsers:
|
125
|
-
"""
|
181
|
+
"""
|
182
|
+
Create and return the full suite of argument parsers used by the Falyx CLI.
|
183
|
+
|
184
|
+
This function builds the root parser and all subcommand parsers used for structured
|
185
|
+
CLI workflows in Falyx. It supports standard subcommands including `run`, `run-all`,
|
186
|
+
`preview`, `list`, and `version`, and integrates with registered `Command` objects
|
187
|
+
to populate dynamic help and usage documentation.
|
188
|
+
|
189
|
+
Args:
|
190
|
+
prog (str | None): Program name to display in help and usage messages.
|
191
|
+
usage (str | None): Optional usage message to override the default.
|
192
|
+
description (str | None): Description for the CLI root parser.
|
193
|
+
epilog (str | None): Epilog message shown after the help text.
|
194
|
+
parents (Sequence[ArgumentParser] | None): Optional parent parsers.
|
195
|
+
prefix_chars (str): Characters that prefix optional arguments.
|
196
|
+
fromfile_prefix_chars (str | None): Prefix character for reading args from file.
|
197
|
+
argument_default (Any): Default value for arguments if not specified.
|
198
|
+
conflict_handler (str): Strategy for resolving conflicting arguments.
|
199
|
+
add_help (bool): Whether to add the `-h/--help` option to the root parser.
|
200
|
+
allow_abbrev (bool): Whether to allow abbreviated long options.
|
201
|
+
exit_on_error (bool): Whether the parser exits on error or raises.
|
202
|
+
commands (dict[str, Command] | None): Optional dictionary of registered commands
|
203
|
+
to populate help and subcommand descriptions dynamically.
|
204
|
+
root_parser (ArgumentParser | None): Custom root parser to use instead of building one.
|
205
|
+
subparsers (_SubParsersAction | None): Optional existing subparser object to extend.
|
206
|
+
|
207
|
+
Returns:
|
208
|
+
FalyxParsers: A structured container of all parsers, including `run`, `run-all`,
|
209
|
+
`preview`, `list`, `version`, and the root parser.
|
210
|
+
|
211
|
+
Raises:
|
212
|
+
TypeError: If `root_parser` is not an instance of ArgumentParser or
|
213
|
+
`subparsers` is not an instance of _SubParsersAction.
|
214
|
+
|
215
|
+
Example:
|
216
|
+
```python
|
217
|
+
>>> parsers = get_arg_parsers(commands=my_command_dict)
|
218
|
+
>>> args = parsers.root.parse_args()
|
219
|
+
```
|
220
|
+
|
221
|
+
Notes:
|
222
|
+
- This function integrates dynamic command usage and descriptions if the
|
223
|
+
`commands` argument is provided.
|
224
|
+
- The `run` parser supports additional options for retry logic and confirmation
|
225
|
+
prompts.
|
226
|
+
- The `run-all` parser executes all commands matching a tag.
|
227
|
+
- Use `falyx run ?[COMMAND]` from the CLI to preview a command.
|
228
|
+
"""
|
126
229
|
if epilog is None:
|
127
230
|
epilog = f"Tip: Use '{prog} run ?[COMMAND]' to preview any command from the CLI."
|
128
231
|
if root_parser is None:
|
falyx/validators.py
CHANGED
@@ -44,10 +44,12 @@ def yes_no_validator() -> Validator:
|
|
44
44
|
return False
|
45
45
|
return True
|
46
46
|
|
47
|
-
return Validator.from_callable(validate, error_message="Enter 'Y' or 'n'.")
|
47
|
+
return Validator.from_callable(validate, error_message="Enter 'Y', 'y' or 'N', 'n'.")
|
48
48
|
|
49
49
|
|
50
|
-
def words_validator(
|
50
|
+
def words_validator(
|
51
|
+
keys: Sequence[str] | KeysView[str], error_message: str | None = None
|
52
|
+
) -> Validator:
|
51
53
|
"""Validator for specific word inputs."""
|
52
54
|
|
53
55
|
def validate(text: str) -> bool:
|
@@ -55,9 +57,10 @@ def words_validator(keys: Sequence[str] | KeysView[str]) -> Validator:
|
|
55
57
|
return False
|
56
58
|
return True
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
60
|
+
if error_message is None:
|
61
|
+
error_message = f"Invalid input. Choices: {{{', '.join(keys)}}}."
|
62
|
+
|
63
|
+
return Validator.from_callable(validate, error_message=error_message)
|
61
64
|
|
62
65
|
|
63
66
|
def word_validator(word: str) -> Validator:
|
@@ -68,7 +71,7 @@ def word_validator(word: str) -> Validator:
|
|
68
71
|
return True
|
69
72
|
return text.upper().strip() == word.upper()
|
70
73
|
|
71
|
-
return Validator.from_callable(validate, error_message=f"Enter '{word}' or 'N'.")
|
74
|
+
return Validator.from_callable(validate, error_message=f"Enter '{word}' or 'N', 'n'.")
|
72
75
|
|
73
76
|
|
74
77
|
class MultiIndexValidator(Validator):
|
falyx/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.59"
|
@@ -10,7 +10,7 @@ falyx/action/action_mixins.py,sha256=oUrjbweCeateshg3tqtbQiGuV8u4GvlioIZCUr9D1m4
|
|
10
10
|
falyx/action/action_types.py,sha256=oG8qIFObZdiU1VZQlnWzR8uBDq8rcxzkCli9A31_tMI,1460
|
11
11
|
falyx/action/base_action.py,sha256=o9Nml70-SEVTXnu9J0-VYnO-t5wZZM0o59lYDth24Po,5829
|
12
12
|
falyx/action/chained_action.py,sha256=oknG4ACr79Yf7jb4jvpp6Au7VJLz3PRqABzUKJLn_eY,9274
|
13
|
-
falyx/action/confirm_action.py,sha256=
|
13
|
+
falyx/action/confirm_action.py,sha256=oXPnZswkQFJ-F-s73vddpF-BRg1wJeVnHjR4K2yN7ow,9085
|
14
14
|
falyx/action/fallback_action.py,sha256=3FGWfoR1MIgY0ZkDNOpKu8p3JqPWzh5ON3943mfgDGs,1708
|
15
15
|
falyx/action/http_action.py,sha256=DNeSBWh58UTFGlfFyTk2GnhS54hpLAJLC0QNbq2cYic,5799
|
16
16
|
falyx/action/io_action.py,sha256=V888tQgAynqsVvkhICnEeE4wRs2vvdTcdlEpDSEbHqo,6128
|
@@ -24,9 +24,9 @@ falyx/action/save_file_action.py,sha256=Pe_j0hZjDNsO14bykzVYM0gkWB3zmpB1cExSN01I
|
|
24
24
|
falyx/action/select_file_action.py,sha256=PcV22_wiPeDoJLIhHRiEUmW8N3pYeqQZMVTscQKXuas,9867
|
25
25
|
falyx/action/selection_action.py,sha256=L1evMm7oAQFGMviZ8nMwFKhWKWe8X7wW6dJPHGxpqAE,15398
|
26
26
|
falyx/action/shell_action.py,sha256=0A_kvZLsYmeLHInMM_4Jpe8GCSnXzGBm7H9PnXPvbAs,4055
|
27
|
-
falyx/action/signal_action.py,sha256=
|
27
|
+
falyx/action/signal_action.py,sha256=GxV-0zqYqODOQUa3-tvFTZ2AS1W1QpW6ExonxmWNWbs,1351
|
28
28
|
falyx/action/user_input_action.py,sha256=Up47lumscxnhORMvaft0X-NWpxTXc2GmMZMua__pGhA,3524
|
29
|
-
falyx/bottom_bar.py,sha256=
|
29
|
+
falyx/bottom_bar.py,sha256=B62N3YCQF_h2Rw_hpc2_FUuLNARI-XIGbQkg-1XvaYE,7405
|
30
30
|
falyx/command.py,sha256=QdcwLEFIaq3a4Lfot4cV3zHbVJNQxwSpShprBgLBkh8,16891
|
31
31
|
falyx/completer.py,sha256=EODbakx5PFAwjNcfuUZPFuSx2Q9MXBlWRZJ2LejF6DI,1686
|
32
32
|
falyx/config.py,sha256=OFEq9pFhV39o6_D7dP_QUDjqEusSQNpgomRsh5AAZYY,9621
|
@@ -35,7 +35,7 @@ falyx/context.py,sha256=SuQxxYuv1cb__EieJyRHp7opO-9T5KsMPxruEjVN36Q,10784
|
|
35
35
|
falyx/debug.py,sha256=pguI0XQcZ-7jte5YUPexAufa1oxxalYO1JgmO6GU3rI,1557
|
36
36
|
falyx/exceptions.py,sha256=58D4BYkyJ7PlpZoNk37GsUsFThm_gIlb2Ex2XXhLklI,1099
|
37
37
|
falyx/execution_registry.py,sha256=RLRMOEmfDElFy4tuC8L9tRyNToX7GJ4GoEBh2Iri8zo,7662
|
38
|
-
falyx/falyx.py,sha256=
|
38
|
+
falyx/falyx.py,sha256=6hKcD1RC-jTPA0WiF9JJ31QkacNJAJwqoqO1zhegwoM,49332
|
39
39
|
falyx/falyx_completer.py,sha256=MsfuZXpfGwbsGG-4Zp-j-vNsNnaote-UAJkJh0s2NZI,5236
|
40
40
|
falyx/hook_manager.py,sha256=TFuHQnAncS_rk6vuw-VSx8bnAppLuHfrZCrzLwqcO9o,2979
|
41
41
|
falyx/hooks.py,sha256=xMfQROib0BNsaQF4AXJpmCiGePoE1f1xpcdibgnVZWM,2913
|
@@ -48,7 +48,7 @@ falyx/parser/__init__.py,sha256=NbxAovKIY-duFTs6DAsdM_OzL7s3VIu19KMOmltX9ts,512
|
|
48
48
|
falyx/parser/argument.py,sha256=MIKUj-hrdLDUK8xuW84_l9ms_t5CoNFpVDmxMZIbW-I,4105
|
49
49
|
falyx/parser/argument_action.py,sha256=rNVeth0eMpkZRU_eT1RPVxOGzD4pbdAMx9Kq07T4mG4,709
|
50
50
|
falyx/parser/command_argument_parser.py,sha256=Ej4gYOxSUOYfLr5b0KkZkC0OkuSUrj54JpuI0D0C6h4,37504
|
51
|
-
falyx/parser/parsers.py,sha256=
|
51
|
+
falyx/parser/parsers.py,sha256=vb-l_NNh5O9L98Lcafhz91flRLxC1BnW6U8JdeabRCw,14118
|
52
52
|
falyx/parser/signature.py,sha256=fSltLEr8ctj1qpbU-OvTMnREjlb8OTG5t-guJFR7j4E,2529
|
53
53
|
falyx/parser/utils.py,sha256=km6WvoPUgVdoIpPwDfr6axyjyy8iZy8xndwBNprI2Lk,2996
|
54
54
|
falyx/prompt_utils.py,sha256=qgk0bXs7mwzflqzWyFhEOTpKQ_ZtMIqGhKeg-ocwNnE,1542
|
@@ -61,10 +61,10 @@ falyx/tagged_table.py,sha256=4SV-SdXFrAhy1JNToeBCvyxT-iWVf6cWY7XETTys4n8,1067
|
|
61
61
|
falyx/themes/__init__.py,sha256=1CZhEUCin9cUk8IGYBUFkVvdHRNNJBEFXccHwpUKZCA,284
|
62
62
|
falyx/themes/colors.py,sha256=4aaeAHJetmeNInI0Zytg4E3YqKfPFelpf04vtjSvsS8,19776
|
63
63
|
falyx/utils.py,sha256=U45xnZFUdoFC4xiji_9S1jHS5V7MvxSDtufP8EgB0SM,6732
|
64
|
-
falyx/validators.py,sha256=
|
65
|
-
falyx/version.py,sha256=
|
66
|
-
falyx-0.1.
|
67
|
-
falyx-0.1.
|
68
|
-
falyx-0.1.
|
69
|
-
falyx-0.1.
|
70
|
-
falyx-0.1.
|
64
|
+
falyx/validators.py,sha256=AXpMGnk1_7J7MAbbol6pkMAiSIdNHoF5pwtA2-xS6H8,6029
|
65
|
+
falyx/version.py,sha256=6ejKyHgulDwYDrT6JBlbHrh83UmxgavrhSuOolniIfI,23
|
66
|
+
falyx-0.1.59.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
|
67
|
+
falyx-0.1.59.dist-info/METADATA,sha256=8C_QBe_shgMdk33zg8PXtdp064Sl0icvqExl8yyGNXY,5561
|
68
|
+
falyx-0.1.59.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
69
|
+
falyx-0.1.59.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
|
70
|
+
falyx-0.1.59.dist-info/RECORD,,
|
File without changes
|
File without changes
|