mirror of
https://github.com/kennethreitz/clint.git
synced 2026-06-05 14:50:17 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa79d0d4ea | |||
| 140d85898d | |||
| 93d10a8acb | |||
| 9392b77dcd | |||
| 1162b46f0b | |||
| 82753f5172 | |||
| 714d06ecfa | |||
| c391eae023 | |||
| 1c1f1c93f9 | |||
| f06e164fc6 | |||
| a226b3f2dc | |||
| e3f283ed6e | |||
| 6a417e5bdf | |||
| 7431c17fe4 |
+36
-10
@@ -1,11 +1,37 @@
|
||||
.idea
|
||||
.project
|
||||
.settings
|
||||
.pydevproject
|
||||
MANIFEST
|
||||
*.pyc
|
||||
.tox
|
||||
build/
|
||||
clint.egg-info/
|
||||
dist/
|
||||
*.py[cod]
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
lib
|
||||
lib64
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
nosetests.xml
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
*.DS_Store
|
||||
*.dylib
|
||||
.idea/
|
||||
docs/_*
|
||||
|
||||
+18
-1
@@ -1,6 +1,16 @@
|
||||
History
|
||||
-------
|
||||
|
||||
0.5.0
|
||||
+++++
|
||||
* Added option prompt
|
||||
|
||||
|
||||
0.4.1
|
||||
+++++
|
||||
* Fix bug in logic that decides whether progress bars should be hidden or not
|
||||
|
||||
|
||||
0.4.0
|
||||
+++++
|
||||
* clint.textui.prompt now has a query function with validators! (thanks to @aeby) - see `examples/prompt.py`
|
||||
@@ -12,39 +22,47 @@ History
|
||||
+++++
|
||||
* Clint now obeys the CLINT_FORCE_COLOR environmental variable
|
||||
|
||||
|
||||
0.3.6
|
||||
+++++
|
||||
* Fixed faulty PyPI deployment
|
||||
|
||||
|
||||
0.3.5
|
||||
+++++
|
||||
* progress.bar is now a context manager - doesn't require an iterable anymore (thanks to @jric)
|
||||
* Bug fixes
|
||||
|
||||
|
||||
0.3.4
|
||||
+++++
|
||||
* Fixed Python 3 basestring deprecation
|
||||
* Fixed examples
|
||||
|
||||
|
||||
0.3.3
|
||||
+++++
|
||||
* Fixed Python 3 build issues
|
||||
* Fixed README and HISTORY being installed to /usr
|
||||
* Support added for bold text
|
||||
|
||||
|
||||
0.3.2
|
||||
+++++
|
||||
* Unknown
|
||||
|
||||
|
||||
0.3.1
|
||||
+++++
|
||||
* Unknown
|
||||
|
||||
|
||||
0.3.0
|
||||
+++++
|
||||
|
||||
* Python 3 support!
|
||||
|
||||
|
||||
0.2.4
|
||||
+++++
|
||||
|
||||
@@ -102,7 +120,6 @@ History
|
||||
* Lots of Examples
|
||||
|
||||
|
||||
|
||||
0.1.0 (2011-03-20)
|
||||
++++++++++++++++++
|
||||
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ I want to quote my console text (like email). ::
|
||||
|
||||
I want to color my console text. ::
|
||||
|
||||
>>> from clint.textui import colored
|
||||
>>> from clint.textui import colored, puts
|
||||
|
||||
>>> puts(colored.red('red text'))
|
||||
red text
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ from .pipes import piped_in
|
||||
|
||||
|
||||
__title__ = 'clint'
|
||||
__version__ = '0.4.0'
|
||||
__build__ = 0x000400
|
||||
__version__ = '0.5.0'
|
||||
__build__ = 0x000500
|
||||
__author__ = 'Kenneth Reitz'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = 'Copyright 2012 Kenneth Reitz'
|
||||
|
||||
@@ -14,11 +14,6 @@ import sys
|
||||
import time
|
||||
|
||||
STREAM = sys.stderr
|
||||
# Only show bar in terminals by default (better for piping, logging etc.)
|
||||
try:
|
||||
HIDE_DEFAULT = not STREAM.isatty()
|
||||
except AttributeError: # output does not support isatty()
|
||||
HIDE_DEFAULT = True
|
||||
|
||||
BAR_TEMPLATE = '%s[%s%s] %i/%i - %s\r'
|
||||
MILL_TEMPLATE = '%s %s %i/%i\r'
|
||||
@@ -48,6 +43,7 @@ class Bar(object):
|
||||
self.label = label
|
||||
self.width = width
|
||||
self.hide = hide
|
||||
# Only show bar in terminals by default (better for piping, logging etc.)
|
||||
if hide is None:
|
||||
try:
|
||||
self.hide = not STREAM.isatty()
|
||||
@@ -107,7 +103,7 @@ class Bar(object):
|
||||
return time.strftime('%H:%M:%S', time.gmtime(seconds))
|
||||
|
||||
|
||||
def bar(it, label='', width=32, hide=HIDE_DEFAULT, empty_char=BAR_EMPTY_CHAR,
|
||||
def bar(it, label='', width=32, hide=None, empty_char=BAR_EMPTY_CHAR,
|
||||
filled_char=BAR_FILLED_CHAR, expected_size=None, every=1):
|
||||
"""Progress iterator. Wrap your iterables with it."""
|
||||
|
||||
@@ -121,7 +117,7 @@ def bar(it, label='', width=32, hide=HIDE_DEFAULT, empty_char=BAR_EMPTY_CHAR,
|
||||
bar.show(i + 1)
|
||||
|
||||
|
||||
def dots(it, label='', hide=HIDE_DEFAULT, every=1):
|
||||
def dots(it, label='', hide=None, every=1):
|
||||
"""Progress iterator. Prints a dot for each item being iterated"""
|
||||
|
||||
count = 0
|
||||
@@ -143,7 +139,7 @@ def dots(it, label='', hide=HIDE_DEFAULT, every=1):
|
||||
STREAM.flush()
|
||||
|
||||
|
||||
def mill(it, label='', hide=HIDE_DEFAULT, expected_size=None, every=1):
|
||||
def mill(it, label='', hide=None, expected_size=None, every=1):
|
||||
"""Progress iterator. Prints a mill while iterating over the items."""
|
||||
|
||||
def _mill_char(_i):
|
||||
|
||||
+93
-1
@@ -14,7 +14,7 @@ from re import match, I
|
||||
|
||||
from .core import puts
|
||||
from .colored import yellow
|
||||
from .validators import RegexValidator
|
||||
from .validators import RegexValidator, OptionValidator
|
||||
|
||||
try:
|
||||
raw_input
|
||||
@@ -88,3 +88,95 @@ def query(prompt, default='', validators=None, batch=False):
|
||||
return user_input
|
||||
except Exception as e:
|
||||
puts(yellow(e.message))
|
||||
|
||||
|
||||
|
||||
def options(prompt, options, default=None, batch=False):
|
||||
'''
|
||||
|
||||
:param prompt:
|
||||
:param options:
|
||||
this can be either a list of strings, in which case it will be presented like:
|
||||
prompt:
|
||||
(1) this is the first string
|
||||
(2) this is the second string
|
||||
(3) this is the third string
|
||||
|
||||
please select 1-3:
|
||||
|
||||
or a list of dictionaries in the format of:
|
||||
{ { 'selector' : 'this is what the user will enter to select the option'
|
||||
'prompt': 'this is the string that will be displayed, this can be omitted if the selector is also a prompt',
|
||||
'return': 'this is what is returned to the calling procedure, if omitted, the option selector will be used' }
|
||||
|
||||
so, to replicate the above, the dict could look like:
|
||||
|
||||
[ {'selector':1,'prompt':'this is the first string','return':1},
|
||||
{'selector':2,'prompt':'this is the second string','return':2},
|
||||
{'selector':3,'prompt':'this is the third string'}
|
||||
|
||||
:param default: should be set to the default selector (if desired)
|
||||
:param batch: True/False, will auto-return the default
|
||||
:return:
|
||||
'''
|
||||
# Build fix options and build validator
|
||||
|
||||
validator_list = []
|
||||
return_dict = {}
|
||||
|
||||
if isinstance(options[0],dict):
|
||||
for item in options:
|
||||
item['selector'] = str(item['selector'])
|
||||
item['prompt'] = str(item['prompt'])
|
||||
if 'return' not in item:
|
||||
item['return'] = item['selector']
|
||||
validator_list.append(item['selector'])
|
||||
return_dict[item['selector']] = item['return']
|
||||
else:
|
||||
options_strings = options
|
||||
options = []
|
||||
for key, opt in enumerate(options_strings):
|
||||
item = {}
|
||||
item['selector'] = str(key+1)
|
||||
item['prompt'] = str(opt)
|
||||
item['return'] = key+1
|
||||
|
||||
return_dict[item['selector']] = item['return']
|
||||
validator_list.append(item['selector'])
|
||||
options.append(item)
|
||||
|
||||
validators = [OptionValidator(validator_list)]
|
||||
|
||||
# Let's build the prompt
|
||||
|
||||
prompt += '\n'
|
||||
|
||||
# building the options list
|
||||
for o in options:
|
||||
prompt += '[{selector}] {prompt}\n'.format(**o)
|
||||
|
||||
prompt += '\n'
|
||||
|
||||
if default:
|
||||
prompt += '[' + default + '] '
|
||||
|
||||
# If input is not valid keep asking
|
||||
while True:
|
||||
# If batch option is True then auto reply
|
||||
# with default input
|
||||
if not batch:
|
||||
user_input = raw_input(prompt).strip() or default
|
||||
else:
|
||||
print(prompt)
|
||||
user_input = ''
|
||||
|
||||
|
||||
# Validate the user input
|
||||
try:
|
||||
for validator in validators:
|
||||
user_input = validator(user_input)
|
||||
# convert user input to defined return value
|
||||
user_input = return_dict[user_input]
|
||||
return user_input
|
||||
except Exception as e:
|
||||
puts(yellow(e.message))
|
||||
|
||||
@@ -102,3 +102,21 @@ class IntegerValidator(object):
|
||||
return int(value)
|
||||
except (TypeError, ValueError):
|
||||
raise ValidationError(self.message)
|
||||
|
||||
class OptionValidator(object):
|
||||
message = 'Select from the list of valid options.'
|
||||
|
||||
def __init__(self, options, message=None):
|
||||
self.options = options
|
||||
if message is not None:
|
||||
self.message = message
|
||||
|
||||
def __call__(self, value):
|
||||
"""
|
||||
Validates that the input is in the options list.
|
||||
"""
|
||||
if value in self.options:
|
||||
return value
|
||||
else:
|
||||
raise ValidationError(self.message)
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
_build/*
|
||||
Vendored
Vendored
@@ -1,3 +0,0 @@
|
||||
*.pyc
|
||||
*.pyo
|
||||
.DS_Store
|
||||
+2
-2
@@ -19,7 +19,7 @@ import clint
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.append(os.path.abspath('_themes'))
|
||||
sys.path.append(os.path.abspath('themes'))
|
||||
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ html_theme = 'kr'
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
html_theme_path = ['_themes']
|
||||
html_theme_path = ['themes']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
|
||||
+8
-1
@@ -15,7 +15,14 @@ if __name__ == '__main__':
|
||||
# Set validators to an empty list for an optional input
|
||||
language = prompt.query("Your favorite tool (optional)?", validators=[])
|
||||
|
||||
# Shows a list of options to select from
|
||||
inst_options = [{'selector':'1','prompt':'Full','return':'full'},
|
||||
{'selector':'2','prompt':'Partial','return':'partial'},
|
||||
{'selector':'3','prompt':'None','return':'no install'}]
|
||||
inst = prompt.options("Full or Partial Install", inst_options)
|
||||
|
||||
# Use a default value and a validator
|
||||
path = prompt.query('Installation Path', default='/usr/local/bin/', validators=[validators.PathValidator()])
|
||||
|
||||
puts(colored.blue('Hi {0}. Install {1} to {2}'.format(name, language or 'nothing', path)))
|
||||
puts(colored.blue('Hi {0}. Install {1} {2} to {3}'.format(name, inst, language or 'nothing', path)))
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ required = ['args']
|
||||
setup(
|
||||
name='clint',
|
||||
version=clint.__version__,
|
||||
description='Python Command-line Application Tools',
|
||||
description='Python Command Line Interface Tools',
|
||||
long_description=open('README.rst').read() + '\n\n' +
|
||||
open('HISTORY.rst').read(),
|
||||
author='Kenneth Reitz',
|
||||
@@ -37,7 +37,7 @@ setup(
|
||||
],
|
||||
install_requires=required,
|
||||
license='ISC',
|
||||
classifiers=(
|
||||
classifiers=[
|
||||
# 'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: Console',
|
||||
'Intended Audience :: Developers',
|
||||
@@ -50,6 +50,8 @@ setup(
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.1',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Topic :: Terminals :: Terminal Emulators/X Terminals',
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user