@@ -88,8 +88,13 @@ def _root_callback(
8888
8989
9090def _print_flattened_help () -> None :
91- """Print a custom help screen with all commands flattened and alphabetized."""
92- import shutil
91+ """Print a Rich-formatted help screen with all commands flattened and alphabetized."""
92+ from rich .console import Console
93+ from rich .panel import Panel
94+ from rich .table import Table
95+ from rich .text import Text
96+
97+ console = Console ()
9398
9499 click_app = typer .main .get_command (app )
95100
@@ -99,50 +104,45 @@ def _print_flattened_help() -> None:
99104 def _walk (group : Any , prefix : str = "" ) -> None :
100105 for name in sorted (group .list_commands (None ) or []): # type: ignore[arg-type]
101106 cmd = group .get_command (None , name ) # type: ignore[arg-type]
102- if cmd is None :
103- continue
104- # Skip hidden commands
105- if getattr (cmd , "hidden" , False ):
107+ if cmd is None or getattr (cmd , "hidden" , False ):
106108 continue
107109 full = f"{ prefix } { name } " .strip () if prefix else name
108110 if hasattr (cmd , "list_commands" ) and cmd .list_commands (None ):
109111 _walk (cmd , full )
110112 else :
111- help_text = cmd .get_short_help_str () or ""
112- commands .append ((full , help_text ))
113+ commands .append ((full , cmd .get_short_help_str () or "" ))
113114
114115 _walk (click_app )
115116 commands .sort (key = lambda x : x [0 ])
116117
117- # Calculate column width
118- width = shutil .get_terminal_size ((80 , 24 )).columns
119- name_width = max ((len (c [0 ]) for c in commands ), default = 20 ) + 2
120- desc_width = max (width - name_width - 4 , 20 )
121-
122- # Print
123- print (f"\n \033 [1mroboflow\033 [0m v{ roboflow .__version__ } " ) # noqa: T201
124- print (f" { _DESCRIPTION } \n " ) # noqa: T201
125-
126- print (" \033 [1mUsage:\033 [0m roboflow [OPTIONS] COMMAND [ARGS]\n " ) # noqa: T201
127-
128- print (" \033 [1mOptions:\033 [0m" ) # noqa: T201
129- options = [
130- (" --api-key, -k <KEY>" , "API key override" ),
131- (" --json, -j" , "Output as JSON (for agents and piping)" ),
132- (" --quiet, -q" , "Suppress progress bars and status messages" ),
133- (" --version, -v" , "Show version" ),
134- (" --workspace, -w <ID>" , "Workspace override" ),
135- (" --help, -h" , "Show this help" ),
136- ]
137- opt_name_width = max (len (o [0 ]) for o in options ) + 2
138- for opt_name , opt_help in options :
139- print (f" { opt_name :<{opt_name_width }} { opt_help } " ) # noqa: T201
140-
141- print ("\n \033 [1mCommands:\033 [0m" ) # noqa: T201
118+ # Usage line
119+ console .print ()
120+ console .print (" Usage: roboflow [OPTIONS] COMMAND [ARGS]..." , highlight = False )
121+ console .print ()
122+ console .print (f" { _DESCRIPTION } " , highlight = False )
123+ console .print ()
124+
125+ # Options panel
126+ opt_table = Table (show_header = False , box = None , padding = (0 , 2 ))
127+ opt_table .add_column (style = "bold" , no_wrap = True )
128+ opt_table .add_column ()
129+ opt_table .add_row ("--api-key -k TEXT" , "API key override (default: $ROBOFLOW_API_KEY or config file)" )
130+ opt_table .add_row ("--json -j" , "Output results as JSON (stable schema, for agents and piping)" )
131+ opt_table .add_row ("--quiet -q" , "Suppress non-essential output (progress bars, status messages)" )
132+ opt_table .add_row ("--version -v" , "Show package version and exit" )
133+ opt_table .add_row ("--workspace -w TEXT" , "Workspace URL or ID override (default: configured default)" )
134+ opt_table .add_row ("--help -h" , "Show this message and exit." )
135+ console .print (Panel (opt_table , title = "Options" , title_align = "left" , border_style = "dim" ))
136+
137+ # Commands panel
138+ cmd_table = Table (show_header = False , box = None , padding = (0 , 2 ))
139+ cmd_table .add_column (style = "bold" , no_wrap = True )
140+ cmd_table .add_column ()
142141 for cmd_name , help_text in commands :
143- truncated = help_text [:desc_width ] if len (help_text ) > desc_width else help_text
144- print (f" { cmd_name :<{name_width }} { truncated } " ) # noqa: T201
145- print () # noqa: T201
142+ cmd_table .add_column
143+ cmd_table .add_row (cmd_name , help_text )
144+ console .print (Panel (cmd_table , title = "Commands" , title_align = "left" , border_style = "dim" ))
145+ console .print ()
146146
147147
148148# ---------------------------------------------------------------------------
@@ -206,9 +206,9 @@ def _walk(group: Any, prefix: str = "") -> None:
206206
207207# "roboflow help" command
208208@app .command ("help" , hidden = True )
209- def help_command (ctx : typer .Context ) -> None :
209+ def help_command (ctx : typer .Context ) -> None : # noqa: ARG001
210210 """Show help information."""
211- print ( ctx . parent . get_help () if ctx . parent else ctx . get_help ()) # noqa: T201
211+ _print_flattened_help ()
212212
213213
214214# ---------------------------------------------------------------------------
@@ -343,6 +343,16 @@ def main() -> None:
343343
344344 sys .argv [1 :] = _reorder_argv (sys .argv [1 :])
345345
346+ # Intercept root-level --help/-h: show our flattened help instead of typer's grouped view.
347+ # Only for the ROOT command (not subcommands like 'roboflow project --help').
348+ if "--help" in sys .argv [1 :] or "-h" in sys .argv [1 :]:
349+ argv = sys .argv [1 :]
350+ help_idx = next ((i for i , a in enumerate (argv ) if a in ("--help" , "-h" )), - 1 )
351+ pre_help = [a for a in argv [:help_idx ] if not a .startswith ("-" )]
352+ if not pre_help :
353+ _print_flattened_help ()
354+ sys .exit (0 )
355+
346356 # In --json mode, intercept Click/typer validation errors and emit
347357 # structured JSON on stderr instead of Rich-formatted text.
348358 json_mode = "--json" in sys .argv or "-j" in sys .argv
0 commit comments