55
66 :license: MIT, see LICENSE for more details.
77"""
8+ import inspect
89import logging
910import os
1011import sys
1516import click
1617
1718import requests
19+ from rich .console import Console , RenderableType
20+ from rich .markup import escape
21+ from rich .text import Text
22+ from rich .highlighter import RegexHighlighter
23+ from rich .panel import Panel
24+ from rich .table import Table
25+ from rich .theme import Theme
26+
27+
1828import SoftLayer
1929from SoftLayer .CLI import environment
2030from SoftLayer .CLI import exceptions
4050 DEFAULT_FORMAT = 'table'
4151
4252
53+ class OptionHighlighter (RegexHighlighter ):
54+ highlights = [
55+ r"(?P<switch>\-\w)" , # single options like -v
56+ r"(?P<option>\-\-[\w\-]+)" , # long options like --verbose
57+ r"(?P<default_option>\[[^\]]+\])" , # anything between [], usually default options
58+
59+ ]
60+
61+ SLCLI_THEME = Theme (
62+ {
63+ "option" : "bold cyan" ,
64+ "switch" : "bold green" ,
65+ "default_option" : "light_pink1" ,
66+ "option_keyword" : "bold cyan" ,
67+ "args_keyword" : "bold green"
68+ }
69+ )
70+
4371class CommandLoader (click .MultiCommand ):
4472 """Loads module for click."""
4573
4674 def __init__ (self , * path , ** attrs ):
4775 click .MultiCommand .__init__ (self , ** attrs )
4876 self .path = path
4977
78+ self .highlighter = OptionHighlighter ()
79+ self .console = Console (
80+ theme = SLCLI_THEME
81+ )
82+
5083 def list_commands (self , ctx ):
5184 """List all sub-commands."""
5285 env = ctx .ensure_object (environment .Environment )
@@ -71,6 +104,78 @@ def get_command(self, ctx, cmd_name):
71104 else :
72105 return module
73106
107+ def format_usage (self , ctx : click .Context , formatter : click .formatting .HelpFormatter ) -> None :
108+ """Formats and colorizes the usage information."""
109+ pieces = self .collect_usage_pieces (ctx )
110+ for index , piece in enumerate (pieces ):
111+ if piece == "[OPTIONS]" :
112+ pieces [index ] = "[bold cyan][OPTIONS][/bold cyan]"
113+ elif piece == "COMMAND [ARGS]..." :
114+ pieces [index ] = "[orange1]COMMAND[/orange1] [bold cyan][ARGS][/bold cyan] ..."
115+ else :
116+ # print(f"OK this was {piece}")
117+ continue
118+ self .console .print (f"[bold red]{ ctx .command_path } [/bold red] { ' ' .join (pieces )} " )
119+
120+ def format_help_text (self , ctx : click .Context , formatter : click .formatting .HelpFormatter ) -> None :
121+ """Writes the help text to the formatter if it exists."""
122+ text = self .help if self .help is not None else ""
123+
124+ if self .deprecated :
125+ text = _ ("(Deprecated) {text}" ).format (text = text )
126+
127+ if text :
128+ text = inspect .cleandoc (text ).partition ("\f " )[0 ]
129+ formatter .write_paragraph ()
130+
131+ with formatter .indentation ():
132+ formatter .write_text (text )
133+
134+ def format_epilog (self , ctx : click .Context , formatter : click .formatting .HelpFormatter ) -> None :
135+ """Writes the epilog into the formatter if it exists."""
136+ if self .epilog :
137+ epilog = inspect .cleandoc (self .epilog )
138+ formatter .write_paragraph ()
139+
140+ with formatter .indentation ():
141+ formatter .write_text (epilog )
142+
143+ def format_options (self , ctx , formatter ):
144+
145+ options_table = Table (highlight = True , box = None , show_header = False )
146+
147+ for param in self .get_params (ctx ):
148+ if len (param .opts ) == 2 :
149+ opt1 = self .highlighter (param .opts [1 ])
150+ opt2 = self .highlighter (param .opts [0 ])
151+ else :
152+ opt2 = self .highlighter (param .opts [0 ])
153+ opt1 = Text ("" )
154+
155+ # Ensures the short option is always in opt1.
156+ if len (opt2 ) == 2 :
157+ opt1 , opt2 = opt2 , opt1
158+
159+ if param .metavar :
160+ opt2 += Text (f" { param .metavar } " , style = "bold yellow" )
161+
162+ options = Text (" " .join (reversed (param .opts )))
163+ help_record = param .get_help_record (ctx )
164+ help_message = ""
165+ if help_record :
166+ help_message = param .get_help_record (ctx )[- 1 ]
167+
168+ if param .metavar :
169+ options += f" { param .metavar } "
170+ options_table .add_row (opt1 , opt2 , self .highlighter (help_message ))
171+
172+ self .console .print (options_table )
173+ self .format_commands (ctx , formatter )
174+
175+ # click.echo(click.style('Hello World!', fg='green'))
176+ # print("HEEEELP")
177+
178+
74179
75180def get_latest_version ():
76181 """Gets the latest version of the Softlayer library."""
@@ -83,6 +188,11 @@ def get_latest_version():
83188 return latest
84189
85190
191+ CONTEXT_SETTINGS = dict (
192+ help_option_names = ['--help' , '-h' ],
193+ auto_envvar_prefix = 'SLCLI' ,
194+ max_content_width = 999
195+ )
86196def get_version_message (ctx , param , value ):
87197 """Gets current and latest release versions message."""
88198 if not value or ctx .resilient_parsing :
@@ -99,15 +209,13 @@ def get_version_message(ctx, param, value):
99209username and api_key need to be configured. The easiest way to do that is to
100210use: 'slcli setup'""" ,
101211 cls = CommandLoader ,
102- context_settings = {'help_option_names' : ['-h' , '--help' ],
103- 'auto_envvar_prefix' : 'SLCLI' ,
104- 'max_content_width' : 999 })
212+ context_settings = CONTEXT_SETTINGS )
105213@click .option ('--format' ,
106214 default = DEFAULT_FORMAT ,
107215 show_default = True ,
108216 help = "Output format" ,
109217 type = click .Choice (VALID_FORMATS ))
110- @click .option ('--config' , '- C' ,
218+ @click .option ('-C' ,
111219 required = False ,
112220 default = click .get_app_dir ('softlayer' , force_posix = True ),
113221 show_default = True ,
@@ -119,7 +227,7 @@ def get_version_message(ctx, param, value):
119227 count = True )
120228@click .option ('--proxy' ,
121229 required = False ,
122- help = "HTTP[S] proxy to be use to make API calls" )
230+ help = "HTTPS or HTTP proxy to be use to make API calls" )
123231@click .option ('--really / --not-really' , '-y' ,
124232 is_flag = True ,
125233 required = False ,
@@ -162,7 +270,7 @@ def cli(env,
162270 env .client .transport = env .vars ['_timings' ]
163271
164272
165- @cli .resultcallback ()
273+ @cli .result_callback ()
166274@environment .pass_env
167275def output_diagnostics (env , result , verbose = 0 , ** kwargs ):
168276 """Output diagnostic information."""
0 commit comments