Cleo 0.4 is now out. Commands have been largely improved and are now easier to use. Helpers have also been improved. Overall, Cleo is now more intuitive.
This version breaks the backward compatibility for the following parts:
- The
DialogHelper
has been replaced by a more robustQuestionHelper
- The
ProgressHelper
has been removed and theProgressBar
class must be used - When using decorators or dictionaries, the signature of the callback has changed and accepts only a
Command
instance
New Commands
The Command
class has been improved, with a new way of describing it via docstring and several helper methods:
Command signature
The definition of a command can now be declared in the docstring:
class GreetCommand(Command):
"""
Greets someone
demo:greet
{name? : Who do you want to greet?}
{--y|yell : If set, the task will yell in uppercase letters}
"""
The handle()
method
The logic of the command now needs to be put in the handle()
method:
class GreetCommand(Command):
"""
Greets someone
demo:greet
{name? : Who do you want to greet?}
{--y|yell : If set, the task will yell in uppercase letters}
"""
def handle(self):
name = self.argument('name')
if name:
text = 'Hello %s' % name
else:
text = 'Hello'
if self.option('yell'):
text = text.upper()
self.line(text)
Helper methods
Commands are now easier to use with new helper methods.
argument()
and option()
These methods make it easier to access command's arguments and options.
name = self.argument('name')
yell = self.option('yell')
line()
This methods writes a new line to the output:
self.line('New line')
A style can also be passed as a second argument:
self.line('New line', 'comment')
The native styles have their own helper methods:
self.info('foo')
self.comment('foo')
self.question('foo')
self.error('foo')
call()
Calls another command:
return_code = self.call('demo:greet', [
('name', 'John'),
('--yell', True)
])
If you want to suppress the output of the executed command,
you can use the call_silent()
method instead.
confirm()
Confirm a question with the user.
confirmed = self.confirm('Continue with this action?', False)
In this case, the user will be asked “Continue with this action?”. If the user answers with y it returns True or False if they answer with n. The second argument to confirm() is the default value to return if the user doesn’t enter any valid input. If the second argument is not provided, True is assumed.
ask()
Prompt the user for input.
name = self.ask('Please enter your name', 'John Doe')
secret()
Prompt the user for input but hide the answer from the console.
password = self.secret('Enter the database password')
choice()
Give the user a single choice from an list of answers.
def handle(self):
color = self.choice(
'Please select your favorite color (defaults to red)',
['red', 'blue', 'yellow'],
0
)
self.line('You have just selected: %s' % color)
render_table()
Format input to textual table.
def handle(self):
headers = ['ISBN', 'Title', 'Author']
rows = [
['99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'],
['9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'],
['960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'],
['80-902734-1-6', 'And Then There Were None', 'Agatha Christie']
]
self.render_table(
headers,
rows
)
You can also use the table()
method to retrieve a Table
instance.
progress_bar()
Creates a new progress bar.
def handle(self):
# Create a new progress bar (50 units)
progress = self.progress_bar(50)
# Start and displays the progress bar
for _ in range(50):
# ... do some work
# Advance the progress bar 1 unit
progress.advance()
# You can also advance the progress bar by more than 1 unit
# progress.advance(3)
# Ensure that the progress bar is at 100%
progress.finish()
set_style()
Sets a new formatting style.
def handle(self):
self.set_style('fire', fg='red', bg='yellow', options=['bold', 'blink'])
self.line('<fire>foo</fire>')
Progress Bar
The ProgressHelper
has been removed and the improved ProgressBar
(or its helper method progress_bar()
)
must now be used instead:
def handle(self):
# Create a new progress bar (50 units)
progress = self.progress_bar(50)
# Start and displays the progress bar
for _ in range(50):
# ... do some work
# Advance the progress bar 1 unit
progress.advance()
# You can also advance the progress bar by more than 1 unit
# progress.advance(3)
# Ensure that the progress bar is at 100%
progress.finish()
Table
The TableHelper
has been deprecated and the improved Table
(or its helper method table()
)
should now be used instead:
def handle(self):
table = self.table()
headers = ['ISBN', 'Title', 'Author']
rows = [
['99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'],
['9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'],
['960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'],
['80-902734-1-6', 'And Then There Were None', 'Agatha Christie']
]
table.set_headers(headers)
table.set_rows(rows)
table.render()
Question Helper
The DialogHelper
has been removed and the improved QuestionHelper
(or one of its helper methods)
must now be used instead:
def handle(self):
confirmed = self.confirm('Continue with this action?', False)
name = self.ask('Please enter your name', 'John Doe')
password = self.secret('Enter the database password')
color = self.choice(
'Please select your favorite color (defaults to red)',
['red', 'blue', 'yellow'],
0
)
More verbosity
Two other levels of verbosity (-vv
and -vvv
) have been added.
Command description format
Commands description can now be output as json and markdown:
console help demo:greet --format json
console help demo:greet --format md
Decorators and dictionaries notation
When using decorators or dictionaries, the signature of the callback has changed and accepts only a Command
instance:
def decorated(c):
"""
:type c: Command
"""
This is so that helper methods can be accessed inside code functions.
Autocompletion
Autocompletion has also been improved, and the old bash_completion.sh
has been removed.
To activate support for autocompletion, pass a complete
keyword when initializing
your application:
application = Application('My Application', '0.1', complete=True)
Now, register completion for your application by running one of the following in a terminal,
replacing [program]
with the command you use to run your application:
# BASH ~4.x, ZSH
source <([program] _completion --generate-hook)
# BASH ~3.x, ZSH
[program] _completion --generate-hook | source /dev/stdin
# BASH (any version)
eval $([program] _completion --generate-hook)
By default this registers completion for the absolute path to you application,
which will work if the program is accessible on your PATH.
You can specify a program name to complete for instead using the -p\--program
option,
which is required if you're using an alias to run the program.
If you want the completion to apply automatically for all new shell sessions,
add the command to your shell's profile (eg. ~/.bash_profile
or ~/.zshrc
)
Fixes
- Values are now properly cast by validators
- Fixing "flag" not being set properly
- Progress bar now behaves properly (Fixes #37)
- The
-n|--no-interaction
option behaves properly (Fixes #38 and #39)
There is a lot more you can do with Cleo, you can just give a look at the documentation: http://cleo.readthedocs.org.