falyx 0.1.43__py3-none-any.whl → 0.1.44__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/command.py CHANGED
@@ -135,6 +135,7 @@ class Command(BaseModel):
135
135
  custom_help: Callable[[], str | None] | None = None
136
136
  auto_args: bool = True
137
137
  arg_metadata: dict[str, str | dict[str, Any]] = Field(default_factory=dict)
138
+ simple_help_signature: bool = False
138
139
 
139
140
  _context: ExecutionContext | None = PrivateAttr(default=None)
140
141
 
@@ -317,6 +318,22 @@ class Command(BaseModel):
317
318
  options_text = self.arg_parser.get_options_text(plain_text=True)
318
319
  return f" {command_keys_text:<20} {options_text} "
319
320
 
321
+ @property
322
+ def help_signature(self) -> str:
323
+ """Generate a help signature for the command."""
324
+ if self.arg_parser and not self.simple_help_signature:
325
+ signature = [self.arg_parser.get_usage()]
326
+ signature.append(f" {self.help_text or self.description}")
327
+ if self.tags:
328
+ signature.append(f" [dim]Tags: {', '.join(self.tags)}[/dim]")
329
+ return "\n".join(signature).strip()
330
+
331
+ command_keys = " | ".join(
332
+ [f"[{self.style}]{self.key}[/{self.style}]"]
333
+ + [f"[{self.style}]{alias}[/{self.style}]" for alias in self.aliases]
334
+ )
335
+ return f"{command_keys} {self.description}"
336
+
320
337
  def log_summary(self) -> None:
321
338
  if self._context:
322
339
  self._context.log_summary()
falyx/falyx.py CHANGED
@@ -284,6 +284,7 @@ class Falyx:
284
284
  action=Action("Exit", action=_noop),
285
285
  aliases=["EXIT", "QUIT"],
286
286
  style=OneColors.DARK_RED,
287
+ simple_help_signature=True,
287
288
  )
288
289
 
289
290
  def _get_history_command(self) -> Command:
@@ -294,60 +295,71 @@ class Falyx:
294
295
  aliases=["HISTORY"],
295
296
  action=Action(name="View Execution History", action=er.summary),
296
297
  style=OneColors.DARK_YELLOW,
298
+ simple_help_signature=True,
297
299
  )
298
300
 
299
- async def _show_help(self):
300
- table = Table(title="[bold cyan]Help Menu[/]", box=box.SIMPLE)
301
- table.add_column("Key", style="bold", no_wrap=True)
302
- table.add_column("Aliases", style="dim", no_wrap=True)
303
- table.add_column("Description", style="dim", overflow="fold")
304
- table.add_column("Tags", style="dim", no_wrap=True)
305
-
306
- for command in self.commands.values():
307
- help_text = command.help_text or command.description
308
- table.add_row(
309
- f"[{command.style}]{command.key}[/]",
310
- ", ".join(command.aliases) if command.aliases else "",
311
- help_text,
312
- ", ".join(command.tags) if command.tags else "",
301
+ async def _show_help(self, tag: str = "") -> None:
302
+ if tag:
303
+ table = Table(
304
+ title=tag.upper(),
305
+ title_justify="left",
306
+ show_header=False,
307
+ box=box.SIMPLE,
308
+ show_footer=False,
313
309
  )
314
-
315
- table.add_row(
316
- f"[{self.exit_command.style}]{self.exit_command.key}[/]",
317
- ", ".join(self.exit_command.aliases),
318
- "Exit this menu or program",
319
- )
320
-
321
- if self.history_command:
322
- table.add_row(
323
- f"[{self.history_command.style}]{self.history_command.key}[/]",
324
- ", ".join(self.history_command.aliases),
325
- "History of executed actions",
310
+ tag_lower = tag.lower()
311
+ commands = [
312
+ command
313
+ for command in self.commands.values()
314
+ if any(tag_lower == tag.lower() for tag in command.tags)
315
+ ]
316
+ for command in commands:
317
+ table.add_row(command.help_signature)
318
+ self.console.print(table)
319
+ return
320
+ else:
321
+ table = Table(
322
+ title="Help",
323
+ title_justify="left",
324
+ title_style=OneColors.LIGHT_YELLOW_b,
325
+ show_header=False,
326
+ show_footer=False,
327
+ box=box.SIMPLE,
326
328
  )
327
-
329
+ for command in self.commands.values():
330
+ table.add_row(command.help_signature)
328
331
  if self.help_command:
329
- table.add_row(
330
- f"[{self.help_command.style}]{self.help_command.key}[/]",
331
- ", ".join(self.help_command.aliases),
332
- "Show this help menu",
333
- )
334
-
335
- self.console.print(table, justify="center")
336
- if self.mode == FalyxMode.MENU:
337
- self.console.print(
338
- f"📦 Tip: '[{OneColors.LIGHT_YELLOW}]?[KEY][/]' to preview a command "
339
- "before running it.\n",
340
- justify="center",
341
- )
332
+ table.add_row(self.help_command.help_signature)
333
+ if self.history_command:
334
+ table.add_row(self.history_command.help_signature)
335
+ table.add_row(self.exit_command.help_signature)
336
+ table.add_row(f"Tip: '[{OneColors.LIGHT_YELLOW}]?[KEY][/]' to preview a command ")
337
+ self.console.print(table)
342
338
 
343
339
  def _get_help_command(self) -> Command:
344
340
  """Returns the help command for the menu."""
341
+ parser = CommandArgumentParser(
342
+ command_key="H",
343
+ command_description="Help",
344
+ command_style=OneColors.LIGHT_YELLOW,
345
+ aliases=["?", "HELP", "LIST"],
346
+ )
347
+ parser.add_argument(
348
+ "-t",
349
+ "--tag",
350
+ nargs="?",
351
+ default="",
352
+ help="Optional tag to filter commands by.",
353
+ )
345
354
  return Command(
346
355
  key="H",
347
- aliases=["HELP", "?"],
356
+ aliases=["?", "HELP", "LIST"],
348
357
  description="Help",
358
+ help_text="Show this help menu",
349
359
  action=Action("Help", self._show_help),
350
360
  style=OneColors.LIGHT_YELLOW,
361
+ arg_parser=parser,
362
+ auto_args=False,
351
363
  )
352
364
 
353
365
  def _get_completer(self) -> WordCompleter:
@@ -568,7 +580,9 @@ class Falyx:
568
580
  if not isinstance(submenu, Falyx):
569
581
  raise NotAFalyxError("submenu must be an instance of Falyx.")
570
582
  self._validate_command_key(key)
571
- self.add_command(key, description, submenu.menu, style=style)
583
+ self.add_command(
584
+ key, description, submenu.menu, style=style, simple_help_signature=True
585
+ )
572
586
  if submenu.exit_command.key == "X":
573
587
  submenu.update_exit_command(key="B", description="Back", aliases=["BACK"])
574
588
 
@@ -630,6 +644,7 @@ class Falyx:
630
644
  custom_help: Callable[[], str | None] | None = None,
631
645
  auto_args: bool = True,
632
646
  arg_metadata: dict[str, str | dict[str, Any]] | None = None,
647
+ simple_help_signature: bool = False,
633
648
  ) -> Command:
634
649
  """Adds an command to the menu, preventing duplicates."""
635
650
  self._validate_command_key(key)
@@ -682,6 +697,7 @@ class Falyx:
682
697
  custom_help=custom_help,
683
698
  auto_args=auto_args,
684
699
  arg_metadata=arg_metadata or {},
700
+ simple_help_signature=simple_help_signature,
685
701
  )
686
702
 
687
703
  if hooks:
@@ -706,16 +722,16 @@ class Falyx:
706
722
  def get_bottom_row(self) -> list[str]:
707
723
  """Returns the bottom row of the table for displaying additional commands."""
708
724
  bottom_row = []
709
- if self.history_command:
710
- bottom_row.append(
711
- f"[{self.history_command.key}] [{self.history_command.style}]"
712
- f"{self.history_command.description}"
713
- )
714
725
  if self.help_command:
715
726
  bottom_row.append(
716
727
  f"[{self.help_command.key}] [{self.help_command.style}]"
717
728
  f"{self.help_command.description}"
718
729
  )
730
+ if self.history_command:
731
+ bottom_row.append(
732
+ f"[{self.history_command.key}] [{self.history_command.style}]"
733
+ f"{self.history_command.description}"
734
+ )
719
735
  bottom_row.append(
720
736
  f"[{self.exit_command.key}] [{self.exit_command.style}]"
721
737
  f"{self.exit_command.description}"
@@ -727,12 +743,14 @@ class Falyx:
727
743
  Build the standard table layout. Developers can subclass or call this
728
744
  in custom tables.
729
745
  """
730
- table = Table(title=self.title, show_header=False, box=box.SIMPLE, expand=True) # type: ignore[arg-type]
746
+ table = Table(title=self.title, show_header=False, box=box.SIMPLE) # type: ignore[arg-type]
731
747
  visible_commands = [item for item in self.commands.items() if not item[1].hidden]
748
+ space = self.console.width // self.columns
732
749
  for chunk in chunks(visible_commands, self.columns):
733
750
  row = []
734
751
  for key, command in chunk:
735
- row.append(f"[{key}] [{command.style}]{command.description}")
752
+ cell = f"[{key}] [{command.style}]{command.description}"
753
+ row.append(f"{cell:<{space}}")
736
754
  table.add_row(*row)
737
755
  bottom_row = self.get_bottom_row()
738
756
  for row in chunks(bottom_row, self.columns):
@@ -1076,7 +1094,7 @@ class Falyx:
1076
1094
  self.register_all_with_debug_hooks()
1077
1095
 
1078
1096
  if self.cli_args.command == "list":
1079
- await self._show_help()
1097
+ await self._show_help(tag=self.cli_args.tag)
1080
1098
  sys.exit(0)
1081
1099
 
1082
1100
  if self.cli_args.command == "version" or self.cli_args.version:
falyx/parsers/parsers.py CHANGED
@@ -255,6 +255,10 @@ def get_arg_parsers(
255
255
  "list", help="List all available commands with tags"
256
256
  )
257
257
 
258
+ list_parser.add_argument(
259
+ "-t", "--tag", help="Filter commands by tag (case-insensitive)", default=None
260
+ )
261
+
258
262
  version_parser = subparsers.add_parser("version", help="Show the Falyx version")
259
263
 
260
264
  return FalyxParsers(
@@ -24,7 +24,6 @@ def infer_args_from_func(
24
24
  metadata = (
25
25
  {"help": raw_metadata} if isinstance(raw_metadata, str) else raw_metadata
26
26
  )
27
-
28
27
  if param.kind not in (
29
28
  inspect.Parameter.POSITIONAL_ONLY,
30
29
  inspect.Parameter.POSITIONAL_OR_KEYWORD,
@@ -35,6 +34,8 @@ def infer_args_from_func(
35
34
  arg_type = (
36
35
  param.annotation if param.annotation is not inspect.Parameter.empty else str
37
36
  )
37
+ if isinstance(arg_type, str):
38
+ arg_type = str
38
39
  default = param.default if param.default is not inspect.Parameter.empty else None
39
40
  is_required = param.default is inspect.Parameter.empty
40
41
  if is_required:
falyx/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.43"
1
+ __version__ = "0.1.44"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: falyx
3
- Version: 0.1.43
3
+ Version: 0.1.44
4
4
  Summary: Reliable and introspectable async CLI action framework.
5
5
  License: MIT
6
6
  Author: Roland Thomas Jr
@@ -23,13 +23,13 @@ falyx/action/signal_action.py,sha256=5UMqvzy7fBnLANGwYUWoe1VRhrr7e-yOVeLdOnCBiJo
23
23
  falyx/action/types.py,sha256=NfZz1ufZuvCgp-he2JIItbnjX7LjOUadjtKbjpRlSIY,1399
24
24
  falyx/action/user_input_action.py,sha256=7kL5G7L0j2LuLvHu-CMwOaHyEisagE7O_2G2EhqWRr8,3483
25
25
  falyx/bottom_bar.py,sha256=iWxgOKWgn5YmREeZBuGA50FzqzEfz1-Vnqm0V_fhldc,7383
26
- falyx/command.py,sha256=JO_kPoEUFnW_0BMP7tvdjfj78uWUSfT3JAo-zOqouPM,15023
26
+ falyx/command.py,sha256=x9IuXT3iAArX9MXZ5yLRyaeqIHqklPV_39UlMs2wuuQ,15752
27
27
  falyx/config.py,sha256=BBDRv5uj0teydBm25eTIvEl9hKQqGGGX-Z6H9EHOHHw,10077
28
28
  falyx/context.py,sha256=NfBpxzFzn-dYP6I3wrtGFucqm__UZo4SSBLmM8yYayE,10330
29
29
  falyx/debug.py,sha256=IRpYtdH8yeXJEsfP5rASALmBQb2U_EwrTudF2GIDdZY,1545
30
30
  falyx/exceptions.py,sha256=kK9k1v7LVNjJSwYztRa9Krhr3ZOI-6Htq2ZjlYICPKg,922
31
31
  falyx/execution_registry.py,sha256=rctsz0mrIHPToLZqylblVjDdKWdq1x_JBc8GwMP5sJ8,4710
32
- falyx/falyx.py,sha256=X4f0O5wgUID0HjlwuH0I88HBLGhlQ1chNeOt1TlDJqw,47559
32
+ falyx/falyx.py,sha256=nMFc-fRqab28gRB7ov62C1YILEZZOAJvExKL-d4tTiI,48088
33
33
  falyx/hook_manager.py,sha256=TFuHQnAncS_rk6vuw-VSx8bnAppLuHfrZCrzLwqcO9o,2979
34
34
  falyx/hooks.py,sha256=xMfQROib0BNsaQF4AXJpmCiGePoE1f1xpcdibgnVZWM,2913
35
35
  falyx/init.py,sha256=VZ3rYMxo7g01EraYATdl_pRN4ZqrsVueo2ZFx54gojo,3326
@@ -39,8 +39,8 @@ falyx/options_manager.py,sha256=dFAnQw543tQ6Xupvh1PwBrhiSWlSACHw8K-sHP_lUh4,2842
39
39
  falyx/parsers/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
40
  falyx/parsers/__init__.py,sha256=ZfPmbtEUechDvgl99-lWhTXmFnXS_FMXJ_xb8KGEJLo,448
41
41
  falyx/parsers/argparse.py,sha256=WB8InZJ_WOaqi6J80IfnxInRyJ7aBCP0sv0zalo8al0,36924
42
- falyx/parsers/parsers.py,sha256=iCFOcNXuYLzmOzv63CPi8mWh7udi-Ok1ZJB80ASe12M,8673
43
- falyx/parsers/signature.py,sha256=i4iOiJxv70sxQYivKKXC_YOsShRUYfcI8Cjq8yVZvMo,2262
42
+ falyx/parsers/parsers.py,sha256=MXWC8OQ3apDaeKfY0O4J8NnkxofWVOCRnKatC00lGm0,8796
43
+ falyx/parsers/signature.py,sha256=PfDe432PYcJDhDXguNzumFqWjDLk13s6jhZF33r__AM,2326
44
44
  falyx/parsers/utils.py,sha256=Z4qLu8NVIprcHK2RDXoISpcDKBUii3n05G9mlgiPDgw,889
45
45
  falyx/prompt_utils.py,sha256=qgk0bXs7mwzflqzWyFhEOTpKQ_ZtMIqGhKeg-ocwNnE,1542
46
46
  falyx/protocols.py,sha256=-9GbCBUzzsEgw2_KOCYqxxzWJuez0eHmwnZp_ShY0jc,493
@@ -53,9 +53,9 @@ falyx/themes/__init__.py,sha256=1CZhEUCin9cUk8IGYBUFkVvdHRNNJBEFXccHwpUKZCA,284
53
53
  falyx/themes/colors.py,sha256=4aaeAHJetmeNInI0Zytg4E3YqKfPFelpf04vtjSvsS8,19776
54
54
  falyx/utils.py,sha256=U45xnZFUdoFC4xiji_9S1jHS5V7MvxSDtufP8EgB0SM,6732
55
55
  falyx/validators.py,sha256=t5iyzVpY8tdC4rfhr4isEfWpD5gNTzjeX_Hbi_Uq6sA,1328
56
- falyx/version.py,sha256=PwEipAcIgfEks4UpVgOERoR8Az-FCfCGocVnb0rkncM,23
57
- falyx-0.1.43.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
58
- falyx-0.1.43.dist-info/METADATA,sha256=qHVTRg3y4xhC6cxIDvkkZ5YuJsm98DEhOOi485g-HUE,5517
59
- falyx-0.1.43.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
60
- falyx-0.1.43.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
61
- falyx-0.1.43.dist-info/RECORD,,
56
+ falyx/version.py,sha256=AoJtnEXXv6E20uj57ChQUsGoLfKG8mvSQpdz97tcyis,23
57
+ falyx-0.1.44.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
58
+ falyx-0.1.44.dist-info/METADATA,sha256=4Ug2vw0YvPHn_0o9o4Wij4XiSHG5Nk_kstjOYPp51mM,5517
59
+ falyx-0.1.44.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
60
+ falyx-0.1.44.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
61
+ falyx-0.1.44.dist-info/RECORD,,
File without changes