Initial commit
This commit is contained in:
361
skills/inquirer-patterns/templates/python/autocomplete_prompt.py
Normal file
361
skills/inquirer-patterns/templates/python/autocomplete_prompt.py
Normal file
@@ -0,0 +1,361 @@
|
||||
"""
|
||||
Autocomplete Prompt Template
|
||||
|
||||
Use for: Large option lists with search
|
||||
Features: Type-ahead, fuzzy matching, suggestions
|
||||
"""
|
||||
|
||||
import questionary
|
||||
from questionary import Choice
|
||||
|
||||
|
||||
# Example: Countries list for autocomplete
|
||||
COUNTRIES = [
|
||||
'Afghanistan', 'Albania', 'Algeria', 'Andorra', 'Angola',
|
||||
'Argentina', 'Armenia', 'Australia', 'Austria', 'Azerbaijan',
|
||||
'Bahamas', 'Bahrain', 'Bangladesh', 'Barbados', 'Belarus',
|
||||
'Belgium', 'Belize', 'Benin', 'Bhutan', 'Bolivia',
|
||||
'Brazil', 'Brunei', 'Bulgaria', 'Burkina Faso', 'Burundi',
|
||||
'Cambodia', 'Cameroon', 'Canada', 'Cape Verde', 'Chad',
|
||||
'Chile', 'China', 'Colombia', 'Comoros', 'Congo',
|
||||
'Costa Rica', 'Croatia', 'Cuba', 'Cyprus', 'Czech Republic',
|
||||
'Denmark', 'Djibouti', 'Dominica', 'Dominican Republic',
|
||||
'Ecuador', 'Egypt', 'El Salvador', 'Estonia', 'Ethiopia',
|
||||
'Fiji', 'Finland', 'France', 'Gabon', 'Gambia',
|
||||
'Georgia', 'Germany', 'Ghana', 'Greece', 'Grenada',
|
||||
'Guatemala', 'Guinea', 'Guyana', 'Haiti', 'Honduras',
|
||||
'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran',
|
||||
'Iraq', 'Ireland', 'Israel', 'Italy', 'Jamaica',
|
||||
'Japan', 'Jordan', 'Kazakhstan', 'Kenya', 'Kuwait',
|
||||
'Laos', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia',
|
||||
'Libya', 'Lithuania', 'Luxembourg', 'Madagascar', 'Malawi',
|
||||
'Malaysia', 'Maldives', 'Mali', 'Malta', 'Mexico',
|
||||
'Moldova', 'Monaco', 'Mongolia', 'Morocco', 'Mozambique',
|
||||
'Myanmar', 'Namibia', 'Nepal', 'Netherlands', 'New Zealand',
|
||||
'Nicaragua', 'Niger', 'Nigeria', 'Norway', 'Oman',
|
||||
'Pakistan', 'Panama', 'Paraguay', 'Peru', 'Philippines',
|
||||
'Poland', 'Portugal', 'Qatar', 'Romania', 'Russia',
|
||||
'Rwanda', 'Saudi Arabia', 'Senegal', 'Serbia', 'Singapore',
|
||||
'Slovakia', 'Slovenia', 'Somalia', 'South Africa', 'South Korea',
|
||||
'Spain', 'Sri Lanka', 'Sudan', 'Sweden', 'Switzerland',
|
||||
'Syria', 'Taiwan', 'Tanzania', 'Thailand', 'Togo',
|
||||
'Tunisia', 'Turkey', 'Uganda', 'Ukraine', 'United Arab Emirates',
|
||||
'United Kingdom', 'United States', 'Uruguay', 'Uzbekistan',
|
||||
'Venezuela', 'Vietnam', 'Yemen', 'Zambia', 'Zimbabwe'
|
||||
]
|
||||
|
||||
# Example: Popular packages
|
||||
POPULAR_PACKAGES = [
|
||||
'express', 'react', 'vue', 'angular', 'next', 'nuxt',
|
||||
'axios', 'lodash', 'moment', 'dayjs', 'uuid', 'dotenv',
|
||||
'typescript', 'eslint', 'prettier', 'jest', 'mocha', 'chai',
|
||||
'webpack', 'vite', 'rollup', 'babel', 'esbuild',
|
||||
'socket.io', 'redis', 'mongodb', 'mongoose', 'sequelize',
|
||||
'prisma', 'typeorm', 'knex', 'pg', 'mysql2',
|
||||
'bcrypt', 'jsonwebtoken', 'passport', 'helmet', 'cors',
|
||||
'multer', 'sharp', 'puppeteer', 'playwright', 'cheerio'
|
||||
]
|
||||
|
||||
|
||||
def autocomplete_prompt_example():
|
||||
"""Example autocomplete prompts"""
|
||||
|
||||
print("\n🔍 Autocomplete Example\n")
|
||||
|
||||
# Country selection with autocomplete
|
||||
country = questionary.autocomplete(
|
||||
"Select your country:",
|
||||
choices=COUNTRIES,
|
||||
validate=lambda text: len(text) > 0 or "Please select a country"
|
||||
).ask()
|
||||
|
||||
# Package selection
|
||||
package = questionary.autocomplete(
|
||||
"Search for an npm package:",
|
||||
choices=POPULAR_PACKAGES
|
||||
).ask()
|
||||
|
||||
# Cities based on country (conditional)
|
||||
city = None
|
||||
cities_by_country = {
|
||||
'United States': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix'],
|
||||
'United Kingdom': ['London', 'Manchester', 'Birmingham', 'Glasgow', 'Liverpool'],
|
||||
'Canada': ['Toronto', 'Vancouver', 'Montreal', 'Calgary', 'Ottawa'],
|
||||
'Australia': ['Sydney', 'Melbourne', 'Brisbane', 'Perth', 'Adelaide'],
|
||||
'Germany': ['Berlin', 'Munich', 'Hamburg', 'Frankfurt', 'Cologne']
|
||||
}
|
||||
|
||||
if country in cities_by_country:
|
||||
city = questionary.autocomplete(
|
||||
"Select city:",
|
||||
choices=cities_by_country[country]
|
||||
).ask()
|
||||
|
||||
answers = {
|
||||
'country': country,
|
||||
'package': package,
|
||||
'city': city
|
||||
}
|
||||
|
||||
print("\n✅ Selections:")
|
||||
import json
|
||||
print(json.dumps(answers, indent=2))
|
||||
|
||||
return answers
|
||||
|
||||
|
||||
def framework_search_example():
|
||||
"""Example: Framework/library search with descriptions"""
|
||||
|
||||
print("\n🔎 Framework Search Example\n")
|
||||
|
||||
frameworks = [
|
||||
'React - UI library by Facebook',
|
||||
'Vue.js - Progressive JavaScript framework',
|
||||
'Angular - Platform for building web apps',
|
||||
'Svelte - Cybernetically enhanced web apps',
|
||||
'Next.js - React framework with SSR',
|
||||
'Nuxt.js - Vue.js framework with SSR',
|
||||
'Remix - Full stack web framework',
|
||||
'SvelteKit - Svelte framework',
|
||||
'Express - Fast Node.js web framework',
|
||||
'Fastify - Fast and low overhead web framework',
|
||||
'NestJS - Progressive Node.js framework',
|
||||
'Koa - Expressive middleware for Node.js'
|
||||
]
|
||||
|
||||
framework = questionary.autocomplete(
|
||||
"Search for a framework:",
|
||||
choices=frameworks
|
||||
).ask()
|
||||
|
||||
# Extract value (remove description)
|
||||
framework_name = framework.split(' - ')[0] if ' - ' in framework else framework
|
||||
|
||||
print(f"\n✅ Selected: {framework_name}")
|
||||
|
||||
return {'framework': framework_name}
|
||||
|
||||
|
||||
def command_search_example():
|
||||
"""Example: Command search with emojis and categories"""
|
||||
|
||||
print("\n⌨️ Command Search Example\n")
|
||||
|
||||
commands = [
|
||||
'📦 install - Install dependencies',
|
||||
'🚀 start - Start development server',
|
||||
'🏗️ build - Build for production',
|
||||
'🧪 test - Run tests',
|
||||
'🔍 lint - Check code quality',
|
||||
'✨ format - Format code',
|
||||
'📝 generate - Generate files',
|
||||
'🔄 update - Update dependencies',
|
||||
'🧹 clean - Clean build artifacts',
|
||||
'🚢 deploy - Deploy application',
|
||||
'📊 analyze - Analyze bundle size',
|
||||
'🐛 debug - Start debugger'
|
||||
]
|
||||
|
||||
command = questionary.autocomplete(
|
||||
"Search for a command:",
|
||||
choices=commands
|
||||
).ask()
|
||||
|
||||
# Extract command name
|
||||
command_name = command.split(' - ')[0].split(' ', 1)[1] if ' - ' in command else command
|
||||
|
||||
print(f"\n✅ Running: {command_name}")
|
||||
|
||||
return {'command': command_name}
|
||||
|
||||
|
||||
def api_endpoint_search():
|
||||
"""Example: API endpoint search"""
|
||||
|
||||
print("\n🔍 API Endpoint Search\n")
|
||||
|
||||
endpoints = [
|
||||
'GET /users - List all users',
|
||||
'GET /users/:id - Get user by ID',
|
||||
'POST /users - Create new user',
|
||||
'PUT /users/:id - Update user',
|
||||
'DELETE /users/:id - Delete user',
|
||||
'GET /posts - List all posts',
|
||||
'GET /posts/:id - Get post by ID',
|
||||
'POST /posts - Create new post',
|
||||
'GET /comments - List comments',
|
||||
'POST /auth/login - User login',
|
||||
'POST /auth/register - User registration',
|
||||
'POST /auth/logout - User logout'
|
||||
]
|
||||
|
||||
endpoint = questionary.autocomplete(
|
||||
"Search API endpoints:",
|
||||
choices=endpoints
|
||||
).ask()
|
||||
|
||||
# Extract endpoint path
|
||||
endpoint_path = endpoint.split(' - ')[0] if ' - ' in endpoint else endpoint
|
||||
|
||||
print(f"\n✅ Selected endpoint: {endpoint_path}")
|
||||
|
||||
return {'endpoint': endpoint_path}
|
||||
|
||||
|
||||
def technology_stack_selection():
|
||||
"""Example: Building technology stack with multiple autocomplete prompts"""
|
||||
|
||||
print("\n🛠️ Technology Stack Selection\n")
|
||||
|
||||
# Programming languages
|
||||
languages = [
|
||||
'JavaScript', 'TypeScript', 'Python', 'Go', 'Rust',
|
||||
'Java', 'C++', 'Ruby', 'PHP', 'Swift', 'Kotlin'
|
||||
]
|
||||
|
||||
language = questionary.autocomplete(
|
||||
"Choose programming language:",
|
||||
choices=languages
|
||||
).ask()
|
||||
|
||||
# Frameworks based on language
|
||||
frameworks_by_language = {
|
||||
'JavaScript': ['React', 'Vue', 'Angular', 'Svelte', 'Express', 'Fastify'],
|
||||
'TypeScript': ['Next.js', 'Nest.js', 'Angular', 'Remix', 'tRPC'],
|
||||
'Python': ['Django', 'Flask', 'FastAPI', 'Tornado', 'Sanic'],
|
||||
'Go': ['Gin', 'Echo', 'Fiber', 'Chi', 'Gorilla'],
|
||||
'Rust': ['Actix', 'Rocket', 'Axum', 'Warp', 'Tide'],
|
||||
'Java': ['Spring', 'Micronaut', 'Quarkus', 'Vert.x'],
|
||||
'Ruby': ['Ruby on Rails', 'Sinatra', 'Hanami']
|
||||
}
|
||||
|
||||
framework_choices = frameworks_by_language.get(language, ['None'])
|
||||
framework = questionary.autocomplete(
|
||||
f"Choose {language} framework:",
|
||||
choices=framework_choices
|
||||
).ask()
|
||||
|
||||
# Databases
|
||||
databases = [
|
||||
'PostgreSQL', 'MySQL', 'MongoDB', 'Redis', 'SQLite',
|
||||
'Cassandra', 'DynamoDB', 'CouchDB', 'Neo4j', 'InfluxDB'
|
||||
]
|
||||
|
||||
database = questionary.autocomplete(
|
||||
"Choose database:",
|
||||
choices=databases
|
||||
).ask()
|
||||
|
||||
# Cloud providers
|
||||
cloud_providers = [
|
||||
'AWS', 'Google Cloud', 'Azure', 'DigitalOcean',
|
||||
'Heroku', 'Vercel', 'Netlify', 'Cloudflare'
|
||||
]
|
||||
|
||||
cloud = questionary.autocomplete(
|
||||
"Choose cloud provider:",
|
||||
choices=cloud_providers
|
||||
).ask()
|
||||
|
||||
stack = {
|
||||
'language': language,
|
||||
'framework': framework,
|
||||
'database': database,
|
||||
'cloud': cloud
|
||||
}
|
||||
|
||||
print("\n✅ Technology Stack:")
|
||||
import json
|
||||
print(json.dumps(stack, indent=2))
|
||||
|
||||
return stack
|
||||
|
||||
|
||||
def file_path_autocomplete():
|
||||
"""Example: File path autocomplete (simulated)"""
|
||||
|
||||
print("\n📁 File Path Autocomplete Example\n")
|
||||
|
||||
# Common project directories
|
||||
directories = [
|
||||
'/home/user/projects/web-app',
|
||||
'/home/user/projects/api-server',
|
||||
'/home/user/projects/cli-tool',
|
||||
'/var/www/html',
|
||||
'/opt/applications',
|
||||
'~/Documents/code',
|
||||
'~/workspace/nodejs',
|
||||
'~/workspace/python'
|
||||
]
|
||||
|
||||
project_path = questionary.autocomplete(
|
||||
"Select project directory:",
|
||||
choices=directories
|
||||
).ask()
|
||||
|
||||
# Common config files
|
||||
config_files = [
|
||||
'package.json',
|
||||
'tsconfig.json',
|
||||
'jest.config.js',
|
||||
'webpack.config.js',
|
||||
'.env',
|
||||
'.gitignore',
|
||||
'README.md',
|
||||
'Dockerfile',
|
||||
'docker-compose.yml'
|
||||
]
|
||||
|
||||
config_file = questionary.autocomplete(
|
||||
"Select config file:",
|
||||
choices=config_files
|
||||
).ask()
|
||||
|
||||
result = {
|
||||
'projectPath': project_path,
|
||||
'configFile': config_file
|
||||
}
|
||||
|
||||
print("\n✅ Selected:")
|
||||
import json
|
||||
print(json.dumps(result, indent=2))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
"""Run autocomplete prompt examples"""
|
||||
try:
|
||||
print("=== Autocomplete Examples ===")
|
||||
|
||||
# Example 1: Basic autocomplete
|
||||
autocomplete_prompt_example()
|
||||
|
||||
# Example 2: Framework search
|
||||
framework_search_example()
|
||||
|
||||
# Example 3: Command search
|
||||
command_search_example()
|
||||
|
||||
# Example 4: API endpoint search
|
||||
api_endpoint_search()
|
||||
|
||||
# Example 5: Technology stack
|
||||
technology_stack_selection()
|
||||
|
||||
# Example 6: File path autocomplete
|
||||
file_path_autocomplete()
|
||||
|
||||
print("\n✅ Autocomplete examples complete!")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n❌ User interrupted prompt")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n\n❌ Error: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
310
skills/inquirer-patterns/templates/python/checkbox_prompt.py
Normal file
310
skills/inquirer-patterns/templates/python/checkbox_prompt.py
Normal file
@@ -0,0 +1,310 @@
|
||||
"""
|
||||
Checkbox Prompt Template
|
||||
|
||||
Use for: Multiple selections from options
|
||||
Features: Space to toggle, Enter to confirm
|
||||
"""
|
||||
|
||||
import questionary
|
||||
from questionary import Choice, Separator, ValidationError, Validator
|
||||
|
||||
|
||||
class MinimumChoicesValidator(Validator):
|
||||
"""Validator to ensure minimum number of choices selected"""
|
||||
|
||||
def __init__(self, minimum=1, message=None):
|
||||
self.minimum = minimum
|
||||
self.message = message or f"You must select at least {minimum} option(s)"
|
||||
|
||||
def validate(self, document):
|
||||
# document.text contains selected choices as list
|
||||
if len(document.text) < self.minimum:
|
||||
raise ValidationError(
|
||||
message=self.message,
|
||||
cursor_position=0
|
||||
)
|
||||
|
||||
|
||||
class MaximumChoicesValidator(Validator):
|
||||
"""Validator to ensure maximum number of choices selected"""
|
||||
|
||||
def __init__(self, maximum=10, message=None):
|
||||
self.maximum = maximum
|
||||
self.message = message or f"Please select no more than {maximum} options"
|
||||
|
||||
def validate(self, document):
|
||||
if len(document.text) > self.maximum:
|
||||
raise ValidationError(
|
||||
message=self.message,
|
||||
cursor_position=0
|
||||
)
|
||||
|
||||
|
||||
def checkbox_prompt_example():
|
||||
"""Example checkbox prompts"""
|
||||
|
||||
print("\n☑️ Checkbox Selection Example\n")
|
||||
|
||||
# Simple checkbox
|
||||
features = questionary.checkbox(
|
||||
"Select features to include:",
|
||||
choices=[
|
||||
'Authentication',
|
||||
'Authorization',
|
||||
'Database Integration',
|
||||
'API Documentation',
|
||||
'Testing Suite',
|
||||
'CI/CD Pipeline',
|
||||
'Monitoring',
|
||||
'Logging'
|
||||
],
|
||||
validate=lambda choices: len(choices) > 0 or "You must select at least one feature"
|
||||
).ask()
|
||||
|
||||
# Checkbox with default selections
|
||||
dev_tools = questionary.checkbox(
|
||||
"Select development tools:",
|
||||
choices=[
|
||||
Choice('ESLint (Linting)', value='eslint', checked=True),
|
||||
Choice('Prettier (Formatting)', value='prettier', checked=True),
|
||||
Choice('Jest (Testing)', value='jest'),
|
||||
Choice('Husky (Git Hooks)', value='husky'),
|
||||
Choice('TypeDoc (Documentation)', value='typedoc'),
|
||||
Choice('Webpack (Bundling)', value='webpack')
|
||||
]
|
||||
).ask()
|
||||
|
||||
# Checkbox with separators and checked defaults
|
||||
plugins = questionary.checkbox(
|
||||
"Select plugins to install:",
|
||||
choices=[
|
||||
Separator('=== Essential ==='),
|
||||
Choice('dotenv - Environment variables', value='dotenv', checked=True),
|
||||
Choice('axios - HTTP client', value='axios', checked=True),
|
||||
Separator('=== Utilities ==='),
|
||||
Choice('lodash - Utility functions', value='lodash'),
|
||||
Choice('dayjs - Date manipulation', value='dayjs'),
|
||||
Choice('uuid - Unique IDs', value='uuid'),
|
||||
Separator('=== Validation ==='),
|
||||
Choice('joi - Schema validation', value='joi'),
|
||||
Choice('zod - TypeScript-first validation', value='zod'),
|
||||
Separator('=== Advanced ==='),
|
||||
Choice('bull - Job queues', value='bull'),
|
||||
Choice('socket.io - WebSockets', value='socket.io')
|
||||
],
|
||||
validate=MaximumChoicesValidator(maximum=10)
|
||||
).ask()
|
||||
|
||||
# Checkbox with emojis
|
||||
permissions = questionary.checkbox(
|
||||
"Grant the following permissions:",
|
||||
choices=[
|
||||
Choice('📁 Read files', value='read', checked=True),
|
||||
Choice('✏️ Write files', value='write'),
|
||||
Choice('🗑️ Delete files', value='delete'),
|
||||
Choice('🌐 Network access', value='network', checked=True),
|
||||
Choice('🖥️ System commands', value='system'),
|
||||
Choice('🔒 Keychain access', value='keychain')
|
||||
]
|
||||
).ask()
|
||||
|
||||
# Validate permissions logic
|
||||
if 'delete' in permissions and 'write' not in permissions:
|
||||
print("\n⚠️ Warning: Delete permission requires write permission")
|
||||
permissions.append('write')
|
||||
|
||||
# Checkbox with validation
|
||||
environments = questionary.checkbox(
|
||||
"Select deployment environments:",
|
||||
choices=[
|
||||
Choice('Development', value='dev', checked=True),
|
||||
Choice('Staging', value='staging'),
|
||||
Choice('Production', value='prod'),
|
||||
Choice('Testing', value='test', checked=True)
|
||||
],
|
||||
validate=lambda choices: (
|
||||
'dev' in choices or "Development environment is required"
|
||||
)
|
||||
).ask()
|
||||
|
||||
# Additional validation
|
||||
if 'prod' in environments and 'staging' not in environments:
|
||||
print("\n⚠️ Warning: Staging environment is recommended before production")
|
||||
|
||||
answers = {
|
||||
'features': features,
|
||||
'devTools': dev_tools,
|
||||
'plugins': plugins,
|
||||
'permissions': permissions,
|
||||
'environments': environments
|
||||
}
|
||||
|
||||
print("\n✅ Selected options:")
|
||||
import json
|
||||
print(json.dumps(answers, indent=2))
|
||||
|
||||
# Example: Process selections
|
||||
print("\n📦 Installing selected features...")
|
||||
for feature in features:
|
||||
print(f" - {feature}")
|
||||
|
||||
return answers
|
||||
|
||||
|
||||
def grouped_checkbox_example():
|
||||
"""Example with logically grouped checkboxes"""
|
||||
|
||||
print("\n📂 Grouped Checkbox Example\n")
|
||||
|
||||
security_features = questionary.checkbox(
|
||||
"Select security features:",
|
||||
choices=[
|
||||
Separator('=== Authentication ==='),
|
||||
Choice('JWT Tokens', value='jwt', checked=True),
|
||||
Choice('OAuth 2.0', value='oauth'),
|
||||
Choice('Session Management', value='session'),
|
||||
Choice('Two-Factor Auth', value='2fa'),
|
||||
Separator('=== Authorization ==='),
|
||||
Choice('Role-Based Access Control', value='rbac', checked=True),
|
||||
Choice('Permission System', value='permissions', checked=True),
|
||||
Choice('API Key Management', value='api-keys'),
|
||||
Separator('=== Security ==='),
|
||||
Choice('Rate Limiting', value='rate-limit', checked=True),
|
||||
Choice('CORS Configuration', value='cors', checked=True),
|
||||
Choice('Input Sanitization', value='sanitization', checked=True),
|
||||
Choice('SQL Injection Prevention', value='sql-prevent', checked=True),
|
||||
Choice('XSS Protection', value='xss-protect', checked=True),
|
||||
Separator('=== Encryption ==='),
|
||||
Choice('Data Encryption at Rest', value='encrypt-rest'),
|
||||
Choice('SSL/TLS', value='ssl', checked=True),
|
||||
Choice('Password Hashing', value='hash', checked=True)
|
||||
],
|
||||
validate=MinimumChoicesValidator(minimum=3, message="Select at least 3 security features")
|
||||
).ask()
|
||||
|
||||
print(f"\n✅ Selected {len(security_features)} security features")
|
||||
return {'securityFeatures': security_features}
|
||||
|
||||
|
||||
def dependent_checkbox_example():
|
||||
"""Example with checkboxes that depend on previous selections"""
|
||||
|
||||
print("\n🔗 Dependent Checkbox Example\n")
|
||||
|
||||
# First checkbox: Select cloud providers
|
||||
cloud_providers = questionary.checkbox(
|
||||
"Select cloud providers:",
|
||||
choices=[
|
||||
Choice('☁️ AWS', value='aws'),
|
||||
Choice('☁️ Google Cloud', value='gcp'),
|
||||
Choice('☁️ Azure', value='azure'),
|
||||
Choice('☁️ DigitalOcean', value='do')
|
||||
],
|
||||
validate=lambda c: len(c) > 0 or "Select at least one cloud provider"
|
||||
).ask()
|
||||
|
||||
# Second checkbox: AWS services (only if AWS selected)
|
||||
aws_services = []
|
||||
if 'aws' in cloud_providers:
|
||||
aws_services = questionary.checkbox(
|
||||
"Select AWS services:",
|
||||
choices=[
|
||||
Choice('EC2 - Virtual Servers', value='ec2'),
|
||||
Choice('Lambda - Serverless', value='lambda'),
|
||||
Choice('S3 - Object Storage', value='s3', checked=True),
|
||||
Choice('RDS - Databases', value='rds'),
|
||||
Choice('CloudFront - CDN', value='cloudfront')
|
||||
]
|
||||
).ask()
|
||||
|
||||
# Third checkbox: GCP services (only if GCP selected)
|
||||
gcp_services = []
|
||||
if 'gcp' in cloud_providers:
|
||||
gcp_services = questionary.checkbox(
|
||||
"Select GCP services:",
|
||||
choices=[
|
||||
Choice('Compute Engine', value='compute'),
|
||||
Choice('Cloud Functions', value='functions'),
|
||||
Choice('Cloud Storage', value='storage', checked=True),
|
||||
Choice('Cloud SQL', value='sql'),
|
||||
Choice('Cloud CDN', value='cdn')
|
||||
]
|
||||
).ask()
|
||||
|
||||
result = {
|
||||
'cloudProviders': cloud_providers,
|
||||
'awsServices': aws_services,
|
||||
'gcpServices': gcp_services
|
||||
}
|
||||
|
||||
print("\n✅ Configuration complete:")
|
||||
import json
|
||||
print(json.dumps(result, indent=2))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def conditional_validation_example():
|
||||
"""Example with conditional validation logic"""
|
||||
|
||||
print("\n🔍 Conditional Validation Example\n")
|
||||
|
||||
database_features = questionary.checkbox(
|
||||
"Select database features:",
|
||||
choices=[
|
||||
Choice('Connection Pooling', value='pool', checked=True),
|
||||
Choice('Migrations', value='migrations', checked=True),
|
||||
Choice('Transactions', value='transactions'),
|
||||
Choice('Replication', value='replication'),
|
||||
Choice('Sharding', value='sharding'),
|
||||
Choice('Caching', value='caching')
|
||||
]
|
||||
).ask()
|
||||
|
||||
# Conditional logic: Sharding requires replication
|
||||
if 'sharding' in database_features and 'replication' not in database_features:
|
||||
print("\n⚠️ Sharding requires replication. Adding replication...")
|
||||
database_features.append('replication')
|
||||
|
||||
# Conditional logic: Caching works best with pooling
|
||||
if 'caching' in database_features and 'pool' not in database_features:
|
||||
add_pooling = questionary.confirm(
|
||||
"Caching works best with connection pooling. Add it?",
|
||||
default=True
|
||||
).ask()
|
||||
if add_pooling:
|
||||
database_features.append('pool')
|
||||
|
||||
print(f"\n✅ Selected {len(database_features)} database features")
|
||||
return {'databaseFeatures': database_features}
|
||||
|
||||
|
||||
def main():
|
||||
"""Run checkbox prompt examples"""
|
||||
try:
|
||||
print("=== Checkbox Prompt Examples ===")
|
||||
|
||||
# Example 1: Basic checkbox selections
|
||||
checkbox_prompt_example()
|
||||
|
||||
# Example 2: Grouped checkboxes
|
||||
grouped_checkbox_example()
|
||||
|
||||
# Example 3: Dependent checkboxes
|
||||
dependent_checkbox_example()
|
||||
|
||||
# Example 4: Conditional validation
|
||||
conditional_validation_example()
|
||||
|
||||
print("\n✅ Checkbox examples complete!")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n❌ User interrupted prompt")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n\n❌ Error: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
501
skills/inquirer-patterns/templates/python/conditional_prompt.py
Normal file
501
skills/inquirer-patterns/templates/python/conditional_prompt.py
Normal file
@@ -0,0 +1,501 @@
|
||||
"""
|
||||
Conditional Prompt Template
|
||||
|
||||
Use for: Dynamic forms based on previous answers
|
||||
Features: Skip logic, dependent questions, branching
|
||||
"""
|
||||
|
||||
import questionary
|
||||
from questionary import Choice, Separator
|
||||
|
||||
|
||||
def conditional_prompt_example():
|
||||
"""Example conditional prompts"""
|
||||
|
||||
print("\n🔀 Conditional Prompt Example\n")
|
||||
|
||||
# First question: Use database?
|
||||
use_database = questionary.confirm(
|
||||
"Do you want to use a database?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
database_config = {}
|
||||
|
||||
if use_database:
|
||||
# Database type
|
||||
database_type = questionary.select(
|
||||
"Select database type:",
|
||||
choices=['PostgreSQL', 'MySQL', 'MongoDB', 'SQLite', 'Redis']
|
||||
).ask()
|
||||
|
||||
database_config['databaseType'] = database_type
|
||||
|
||||
# Host and port (not for SQLite)
|
||||
if database_type != 'SQLite':
|
||||
database_host = questionary.text(
|
||||
"Database host:",
|
||||
default="localhost"
|
||||
).ask()
|
||||
|
||||
# Default ports based on database type
|
||||
default_ports = {
|
||||
'PostgreSQL': '5432',
|
||||
'MySQL': '3306',
|
||||
'MongoDB': '27017',
|
||||
'Redis': '6379'
|
||||
}
|
||||
|
||||
database_port = questionary.text(
|
||||
"Database port:",
|
||||
default=default_ports.get(database_type, '5432')
|
||||
).ask()
|
||||
|
||||
database_config['host'] = database_host
|
||||
database_config['port'] = database_port
|
||||
|
||||
# Database name
|
||||
database_name = questionary.text(
|
||||
"Database name:",
|
||||
validate=lambda text: len(text) > 0 or "Database name required"
|
||||
).ask()
|
||||
|
||||
database_config['databaseName'] = database_name
|
||||
|
||||
# Authentication
|
||||
use_authentication = questionary.confirm(
|
||||
"Do you want to use authentication?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
if use_authentication:
|
||||
database_username = questionary.text(
|
||||
"Database username:",
|
||||
validate=lambda text: len(text) > 0 or "Username required"
|
||||
).ask()
|
||||
|
||||
database_password = questionary.password(
|
||||
"Database password:"
|
||||
).ask()
|
||||
|
||||
database_config['useAuthentication'] = True
|
||||
database_config['username'] = database_username
|
||||
# Don't store actual password in answers
|
||||
|
||||
# SSL (only for remote hosts)
|
||||
if database_type != 'SQLite' and database_config.get('host') != 'localhost':
|
||||
use_ssl = questionary.confirm(
|
||||
"Use SSL connection?",
|
||||
default=False
|
||||
).ask()
|
||||
|
||||
if use_ssl:
|
||||
ssl_cert_path = questionary.text(
|
||||
"Path to SSL certificate:",
|
||||
validate=lambda text: len(text) > 0 or "SSL certificate path required"
|
||||
).ask()
|
||||
|
||||
database_config['useSSL'] = True
|
||||
database_config['sslCertPath'] = ssl_cert_path
|
||||
|
||||
answers = {
|
||||
'useDatabase': use_database,
|
||||
'databaseConfig': database_config if use_database else None
|
||||
}
|
||||
|
||||
print("\n✅ Configuration:")
|
||||
import json
|
||||
print(json.dumps(answers, indent=2))
|
||||
|
||||
return answers
|
||||
|
||||
|
||||
def deployment_wizard():
|
||||
"""Example: Deployment configuration wizard"""
|
||||
|
||||
print("\n🚀 Deployment Configuration Wizard\n")
|
||||
|
||||
# Environment
|
||||
environment = questionary.select(
|
||||
"Select deployment environment:",
|
||||
choices=['Development', 'Staging', 'Production']
|
||||
).ask()
|
||||
|
||||
config = {'environment': environment}
|
||||
|
||||
# Docker
|
||||
use_docker = questionary.confirm(
|
||||
"Deploy using Docker?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
config['useDocker'] = use_docker
|
||||
|
||||
if use_docker:
|
||||
docker_image = questionary.text(
|
||||
"Docker image name:",
|
||||
default="myapp:latest",
|
||||
validate=lambda text: len(text) > 0 or "Docker image name required"
|
||||
).ask()
|
||||
|
||||
config['dockerImage'] = docker_image
|
||||
|
||||
registry = questionary.select(
|
||||
"Container registry:",
|
||||
choices=[
|
||||
'Docker Hub',
|
||||
'GitHub Container Registry',
|
||||
'AWS ECR',
|
||||
'Google Artifact Registry'
|
||||
]
|
||||
).ask()
|
||||
|
||||
config['registry'] = registry
|
||||
|
||||
# Platform
|
||||
platform = questionary.select(
|
||||
"Deployment platform:",
|
||||
choices=[
|
||||
'AWS', 'Google Cloud', 'Azure',
|
||||
'DigitalOcean', 'Vercel', 'Netlify', 'Self-hosted'
|
||||
]
|
||||
).ask()
|
||||
|
||||
config['platform'] = platform
|
||||
|
||||
# Platform-specific configuration
|
||||
if platform == 'AWS':
|
||||
aws_service = questionary.select(
|
||||
"AWS service:",
|
||||
choices=['ECS', 'EKS', 'Lambda', 'Elastic Beanstalk', 'EC2']
|
||||
).ask()
|
||||
config['awsService'] = aws_service
|
||||
|
||||
# Auto-scaling (only for certain services)
|
||||
if aws_service in ['ECS', 'EKS']:
|
||||
auto_scale = questionary.confirm(
|
||||
"Enable auto-scaling?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
config['autoScale'] = auto_scale
|
||||
|
||||
if auto_scale:
|
||||
min_instances = questionary.text(
|
||||
"Minimum instances:",
|
||||
default="1",
|
||||
validate=lambda text: text.isdigit() and int(text) > 0 or "Must be at least 1"
|
||||
).ask()
|
||||
|
||||
max_instances = questionary.text(
|
||||
"Maximum instances:",
|
||||
default="10",
|
||||
validate=lambda text: text.isdigit() and int(text) >= int(min_instances) or f"Must be at least {min_instances}"
|
||||
).ask()
|
||||
|
||||
config['minInstances'] = int(min_instances)
|
||||
config['maxInstances'] = int(max_instances)
|
||||
|
||||
elif platform == 'Google Cloud':
|
||||
gcp_service = questionary.select(
|
||||
"Google Cloud service:",
|
||||
choices=['Cloud Run', 'GKE', 'App Engine', 'Compute Engine']
|
||||
).ask()
|
||||
config['gcpService'] = gcp_service
|
||||
|
||||
# CDN (only for production)
|
||||
if environment == 'Production':
|
||||
use_cdn = questionary.confirm(
|
||||
"Use CDN for static assets?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
config['useCDN'] = use_cdn
|
||||
|
||||
if use_cdn:
|
||||
cdn_provider = questionary.select(
|
||||
"CDN provider:",
|
||||
choices=['CloudFlare', 'AWS CloudFront', 'Google Cloud CDN', 'Azure CDN']
|
||||
).ask()
|
||||
config['cdnProvider'] = cdn_provider
|
||||
|
||||
# Monitoring
|
||||
setup_monitoring = questionary.confirm(
|
||||
"Setup monitoring?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
if setup_monitoring:
|
||||
monitoring_tools = questionary.checkbox(
|
||||
"Select monitoring tools:",
|
||||
choices=['Prometheus', 'Grafana', 'Datadog', 'New Relic', 'Sentry'],
|
||||
validate=lambda choices: len(choices) > 0 or "Select at least one tool"
|
||||
).ask()
|
||||
|
||||
config['monitoringTools'] = monitoring_tools
|
||||
|
||||
print("\n✅ Deployment configuration complete!")
|
||||
import json
|
||||
print(json.dumps(config, indent=2))
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def feature_flag_wizard():
|
||||
"""Example: Feature flag configuration"""
|
||||
|
||||
print("\n🎛️ Feature Flag Configuration\n")
|
||||
|
||||
# Feature name
|
||||
feature_name = questionary.text(
|
||||
"Feature name:",
|
||||
validate=lambda text: text and text.replace('-', '').replace('_', '').islower() or "Use lowercase, hyphens, underscores only"
|
||||
).ask()
|
||||
|
||||
# Enabled by default
|
||||
enabled_by_default = questionary.confirm(
|
||||
"Enabled by default?",
|
||||
default=False
|
||||
).ask()
|
||||
|
||||
config = {
|
||||
'featureName': feature_name,
|
||||
'enabledByDefault': enabled_by_default
|
||||
}
|
||||
|
||||
# Rollout strategy
|
||||
rollout_strategy = questionary.select(
|
||||
"Rollout strategy:",
|
||||
choices=[
|
||||
'All users',
|
||||
'Percentage rollout',
|
||||
'User targeting',
|
||||
'Beta users only',
|
||||
'Manual control'
|
||||
]
|
||||
).ask()
|
||||
|
||||
config['rolloutStrategy'] = rollout_strategy
|
||||
|
||||
# Percentage rollout
|
||||
if rollout_strategy == 'Percentage rollout':
|
||||
rollout_percentage = questionary.text(
|
||||
"Rollout percentage (0-100):",
|
||||
default="10",
|
||||
validate=lambda text: text.isdigit() and 0 <= int(text) <= 100 or "Must be between 0 and 100"
|
||||
).ask()
|
||||
|
||||
config['rolloutPercentage'] = int(rollout_percentage)
|
||||
|
||||
# User targeting
|
||||
if rollout_strategy == 'User targeting':
|
||||
target_user_groups = questionary.checkbox(
|
||||
"Target user groups:",
|
||||
choices=[
|
||||
'Beta testers',
|
||||
'Premium users',
|
||||
'Internal team',
|
||||
'Early adopters',
|
||||
'Specific regions'
|
||||
],
|
||||
validate=lambda choices: len(choices) > 0 or "Select at least one group"
|
||||
).ask()
|
||||
|
||||
config['targetUserGroups'] = target_user_groups
|
||||
|
||||
# Specific regions
|
||||
if 'Specific regions' in target_user_groups:
|
||||
target_regions = questionary.checkbox(
|
||||
"Target regions:",
|
||||
choices=[
|
||||
'North America',
|
||||
'Europe',
|
||||
'Asia Pacific',
|
||||
'South America',
|
||||
'Africa'
|
||||
]
|
||||
).ask()
|
||||
|
||||
config['targetRegions'] = target_regions
|
||||
|
||||
# Metrics
|
||||
enable_metrics = questionary.confirm(
|
||||
"Track feature usage metrics?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
if enable_metrics:
|
||||
metrics = questionary.checkbox(
|
||||
"Select metrics to track:",
|
||||
choices=[
|
||||
'Usage count',
|
||||
'User adoption rate',
|
||||
'Performance impact',
|
||||
'Error rate',
|
||||
'User feedback'
|
||||
]
|
||||
).ask()
|
||||
|
||||
config['metrics'] = metrics
|
||||
|
||||
# Expiration
|
||||
add_expiration_date = questionary.confirm(
|
||||
"Set feature flag expiration?",
|
||||
default=False
|
||||
).ask()
|
||||
|
||||
if add_expiration_date:
|
||||
expiration_date = questionary.text(
|
||||
"Expiration date (YYYY-MM-DD):",
|
||||
validate=lambda text: len(text) == 10 and text.count('-') == 2 or "Use format YYYY-MM-DD"
|
||||
).ask()
|
||||
|
||||
config['expirationDate'] = expiration_date
|
||||
|
||||
print("\n✅ Feature flag configured!")
|
||||
import json
|
||||
print(json.dumps(config, indent=2))
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def cicd_pipeline_wizard():
|
||||
"""Example: CI/CD pipeline setup"""
|
||||
|
||||
print("\n⚙️ CI/CD Pipeline Configuration\n")
|
||||
|
||||
# Provider
|
||||
provider = questionary.select(
|
||||
"CI/CD provider:",
|
||||
choices=['GitHub Actions', 'GitLab CI', 'CircleCI', 'Jenkins', 'Travis CI']
|
||||
).ask()
|
||||
|
||||
config = {'provider': provider}
|
||||
|
||||
# Triggers
|
||||
triggers = questionary.checkbox(
|
||||
"Pipeline triggers:",
|
||||
choices=[
|
||||
'Push to main/master',
|
||||
'Pull request',
|
||||
'Tag creation',
|
||||
'Manual trigger',
|
||||
'Scheduled (cron)'
|
||||
],
|
||||
default=['Push to main/master', 'Pull request']
|
||||
).ask()
|
||||
|
||||
config['triggers'] = triggers
|
||||
|
||||
# Cron schedule
|
||||
if 'Scheduled (cron)' in triggers:
|
||||
cron_schedule = questionary.text(
|
||||
"Cron schedule:",
|
||||
default="0 2 * * *",
|
||||
validate=lambda text: len(text.split()) == 5 or "Invalid cron format (5 parts required)"
|
||||
).ask()
|
||||
|
||||
config['cronSchedule'] = cron_schedule
|
||||
|
||||
# Stages
|
||||
stages = questionary.checkbox(
|
||||
"Pipeline stages:",
|
||||
choices=['Build', 'Test', 'Lint', 'Security scan', 'Deploy'],
|
||||
default=['Build', 'Test', 'Deploy'],
|
||||
validate=lambda choices: len(choices) > 0 or "Select at least one stage"
|
||||
).ask()
|
||||
|
||||
config['stages'] = stages
|
||||
|
||||
# Test types
|
||||
if 'Test' in stages:
|
||||
test_types = questionary.checkbox(
|
||||
"Test types to run:",
|
||||
choices=[
|
||||
'Unit tests',
|
||||
'Integration tests',
|
||||
'E2E tests',
|
||||
'Performance tests'
|
||||
]
|
||||
).ask()
|
||||
|
||||
config['testTypes'] = test_types
|
||||
|
||||
# Security tools
|
||||
if 'Security scan' in stages:
|
||||
security_tools = questionary.checkbox(
|
||||
"Security scanning tools:",
|
||||
choices=['Snyk', 'Dependabot', 'SonarQube', 'OWASP Dependency Check']
|
||||
).ask()
|
||||
|
||||
config['securityTools'] = security_tools
|
||||
|
||||
# Deploy environments
|
||||
if 'Deploy' in stages:
|
||||
deploy_environments = questionary.checkbox(
|
||||
"Deployment environments:",
|
||||
choices=['Development', 'Staging', 'Production'],
|
||||
default=['Staging', 'Production']
|
||||
).ask()
|
||||
|
||||
config['deployEnvironments'] = deploy_environments
|
||||
|
||||
# Approval for production
|
||||
if 'Production' in deploy_environments:
|
||||
require_approval = questionary.confirm(
|
||||
"Require manual approval for production?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
config['requireApproval'] = require_approval
|
||||
|
||||
# Notifications
|
||||
enable_notifications = questionary.confirm(
|
||||
"Enable build notifications?",
|
||||
default=True
|
||||
).ask()
|
||||
|
||||
if enable_notifications:
|
||||
notification_channels = questionary.checkbox(
|
||||
"Notification channels:",
|
||||
choices=['Email', 'Slack', 'Discord', 'Microsoft Teams']
|
||||
).ask()
|
||||
|
||||
config['notificationChannels'] = notification_channels
|
||||
|
||||
print("\n✅ CI/CD pipeline configured!")
|
||||
import json
|
||||
print(json.dumps(config, indent=2))
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def main():
|
||||
"""Run conditional prompt examples"""
|
||||
try:
|
||||
print("=== Conditional Prompt Examples ===")
|
||||
|
||||
# Example 1: Database configuration
|
||||
conditional_prompt_example()
|
||||
|
||||
# Example 2: Deployment wizard
|
||||
deployment_wizard()
|
||||
|
||||
# Example 3: Feature flag configuration
|
||||
feature_flag_wizard()
|
||||
|
||||
# Example 4: CI/CD pipeline setup
|
||||
cicd_pipeline_wizard()
|
||||
|
||||
print("\n✅ Conditional prompt examples complete!")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n❌ User interrupted prompt")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n\n❌ Error: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
221
skills/inquirer-patterns/templates/python/list_prompt.py
Normal file
221
skills/inquirer-patterns/templates/python/list_prompt.py
Normal file
@@ -0,0 +1,221 @@
|
||||
"""
|
||||
List Selection Prompt Template
|
||||
|
||||
Use for: Single choice from predefined options
|
||||
Features: Arrow key navigation, search filtering
|
||||
"""
|
||||
|
||||
import questionary
|
||||
from questionary import Choice, Separator
|
||||
|
||||
|
||||
def list_prompt_example():
|
||||
"""Example list selection prompts"""
|
||||
|
||||
print("\n📋 List Selection Example\n")
|
||||
|
||||
# Simple list
|
||||
framework = questionary.select(
|
||||
"Choose your preferred framework:",
|
||||
choices=[
|
||||
'React',
|
||||
'Vue',
|
||||
'Angular',
|
||||
'Svelte',
|
||||
'Next.js',
|
||||
'Nuxt.js'
|
||||
],
|
||||
default='React'
|
||||
).ask()
|
||||
|
||||
# List with values
|
||||
language = questionary.select(
|
||||
"Choose programming language:",
|
||||
choices=[
|
||||
Choice('JavaScript', value='js'),
|
||||
Choice('TypeScript', value='ts'),
|
||||
Choice('Python', value='py'),
|
||||
Choice('Ruby', value='rb'),
|
||||
Choice('Go', value='go')
|
||||
],
|
||||
default='ts'
|
||||
).ask()
|
||||
|
||||
# List with descriptions
|
||||
package_manager = questionary.select(
|
||||
"Choose package manager:",
|
||||
choices=[
|
||||
Choice('npm - Node Package Manager', value='npm', shortcut_key='n'),
|
||||
Choice('yarn - Fast, reliable package manager', value='yarn', shortcut_key='y'),
|
||||
Choice('pnpm - Fast, disk space efficient', value='pnpm', shortcut_key='p'),
|
||||
Choice('bun - All-in-one toolkit', value='bun', shortcut_key='b')
|
||||
]
|
||||
).ask()
|
||||
|
||||
# List with separators
|
||||
environment = questionary.select(
|
||||
"Select deployment environment:",
|
||||
choices=[
|
||||
Separator('--- Cloud Platforms ---'),
|
||||
'AWS',
|
||||
'Google Cloud',
|
||||
'Azure',
|
||||
Separator('--- Serverless ---'),
|
||||
'Vercel',
|
||||
'Netlify',
|
||||
'Cloudflare Workers',
|
||||
Separator('--- Self-hosted ---'),
|
||||
'Docker',
|
||||
'Kubernetes'
|
||||
]
|
||||
).ask()
|
||||
|
||||
# List with emojis and styling
|
||||
database = questionary.select(
|
||||
"Choose database:",
|
||||
choices=[
|
||||
Choice('🐘 PostgreSQL (Relational)', value='postgresql'),
|
||||
Choice('🐬 MySQL (Relational)', value='mysql'),
|
||||
Choice('🍃 MongoDB (Document)', value='mongodb'),
|
||||
Choice('⚡ Redis (Key-Value)', value='redis'),
|
||||
Choice('📊 SQLite (Embedded)', value='sqlite'),
|
||||
Choice('🔥 Supabase (PostgreSQL + APIs)', value='supabase')
|
||||
],
|
||||
use_shortcuts=True,
|
||||
use_arrow_keys=True
|
||||
).ask()
|
||||
|
||||
answers = {
|
||||
'framework': framework,
|
||||
'language': language,
|
||||
'packageManager': package_manager,
|
||||
'environment': environment,
|
||||
'database': database
|
||||
}
|
||||
|
||||
print("\n✅ Selections:")
|
||||
import json
|
||||
print(json.dumps(answers, indent=2))
|
||||
|
||||
return answers
|
||||
|
||||
|
||||
def dynamic_list_example():
|
||||
"""Example with dynamic choices based on context"""
|
||||
|
||||
print("\n🔄 Dynamic List Example\n")
|
||||
|
||||
# First selection
|
||||
project_type = questionary.select(
|
||||
"Project type:",
|
||||
choices=['Web Application', 'CLI Tool', 'API/Backend', 'Library']
|
||||
).ask()
|
||||
|
||||
# Dynamic framework choices based on project type
|
||||
framework_choices = {
|
||||
'Web Application': ['React', 'Vue', 'Angular', 'Svelte', 'Next.js'],
|
||||
'CLI Tool': ['Commander.js', 'Yargs', 'Click', 'Typer', 'Cobra'],
|
||||
'API/Backend': ['Express', 'Fastify', 'Flask', 'FastAPI', 'Gin'],
|
||||
'Library': ['TypeScript', 'JavaScript', 'Python', 'Go', 'Rust']
|
||||
}
|
||||
|
||||
framework = questionary.select(
|
||||
f"Choose framework for {project_type}:",
|
||||
choices=framework_choices.get(project_type, ['None'])
|
||||
).ask()
|
||||
|
||||
print(f"\n✅ Selected: {project_type} with {framework}")
|
||||
|
||||
return {'projectType': project_type, 'framework': framework}
|
||||
|
||||
|
||||
def categorized_list_example():
|
||||
"""Example with categorized options"""
|
||||
|
||||
print("\n📂 Categorized List Example\n")
|
||||
|
||||
cloud_service = questionary.select(
|
||||
"Choose cloud service:",
|
||||
choices=[
|
||||
Separator('=== Compute ==='),
|
||||
Choice('EC2 - Virtual Servers', value='ec2'),
|
||||
Choice('Lambda - Serverless Functions', value='lambda'),
|
||||
Choice('ECS - Container Service', value='ecs'),
|
||||
Choice('EKS - Kubernetes Service', value='eks'),
|
||||
Separator('=== Storage ==='),
|
||||
Choice('S3 - Object Storage', value='s3'),
|
||||
Choice('EBS - Block Storage', value='ebs'),
|
||||
Choice('EFS - File System', value='efs'),
|
||||
Separator('=== Database ==='),
|
||||
Choice('RDS - Relational Database', value='rds'),
|
||||
Choice('DynamoDB - NoSQL Database', value='dynamodb'),
|
||||
Choice('ElastiCache - In-Memory Cache', value='elasticache'),
|
||||
Separator('=== Other ==='),
|
||||
Choice('CloudFront - CDN', value='cloudfront'),
|
||||
Choice('Route53 - DNS', value='route53'),
|
||||
Choice('SQS - Message Queue', value='sqs')
|
||||
],
|
||||
use_indicator=True
|
||||
).ask()
|
||||
|
||||
print(f"\n✅ Selected: {cloud_service}")
|
||||
|
||||
return {'cloudService': cloud_service}
|
||||
|
||||
|
||||
def numbered_list_example():
|
||||
"""Example with numbered choices for easier selection"""
|
||||
|
||||
print("\n🔢 Numbered List Example\n")
|
||||
|
||||
languages = [
|
||||
'Python', 'JavaScript', 'TypeScript', 'Go', 'Rust',
|
||||
'Java', 'C++', 'Ruby', 'PHP', 'Swift'
|
||||
]
|
||||
|
||||
# Add numbers to choices for easier reference
|
||||
numbered_choices = [
|
||||
Choice(f"{i+1}. {lang}", value=lang)
|
||||
for i, lang in enumerate(languages)
|
||||
]
|
||||
|
||||
language = questionary.select(
|
||||
"Choose programming language:",
|
||||
choices=numbered_choices,
|
||||
use_shortcuts=False # Disable letter shortcuts when using numbers
|
||||
).ask()
|
||||
|
||||
print(f"\n✅ Selected: {language}")
|
||||
|
||||
return {'language': language}
|
||||
|
||||
|
||||
def main():
|
||||
"""Run list prompt examples"""
|
||||
try:
|
||||
print("=== List Selection Examples ===")
|
||||
|
||||
# Example 1: Basic list selections
|
||||
list_prompt_example()
|
||||
|
||||
# Example 2: Dynamic choices
|
||||
dynamic_list_example()
|
||||
|
||||
# Example 3: Categorized options
|
||||
categorized_list_example()
|
||||
|
||||
# Example 4: Numbered list
|
||||
numbered_list_example()
|
||||
|
||||
print("\n✅ List selection examples complete!")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n❌ User interrupted prompt")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n\n❌ Error: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
366
skills/inquirer-patterns/templates/python/password_prompt.py
Normal file
366
skills/inquirer-patterns/templates/python/password_prompt.py
Normal file
@@ -0,0 +1,366 @@
|
||||
"""
|
||||
Password Prompt Template
|
||||
|
||||
Use for: Sensitive input (credentials, tokens)
|
||||
Features: Hidden input, confirmation, validation
|
||||
"""
|
||||
|
||||
import questionary
|
||||
import re
|
||||
from questionary import ValidationError, Validator
|
||||
|
||||
|
||||
class PasswordStrengthValidator(Validator):
|
||||
"""Validator for password strength requirements"""
|
||||
|
||||
def __init__(self, min_length=8, require_uppercase=True, require_lowercase=True,
|
||||
require_digit=True, require_special=True):
|
||||
self.min_length = min_length
|
||||
self.require_uppercase = require_uppercase
|
||||
self.require_lowercase = require_lowercase
|
||||
self.require_digit = require_digit
|
||||
self.require_special = require_special
|
||||
|
||||
def validate(self, document):
|
||||
password = document.text
|
||||
issues = []
|
||||
|
||||
if len(password) < self.min_length:
|
||||
issues.append(f"at least {self.min_length} characters")
|
||||
|
||||
if self.require_uppercase and not re.search(r'[A-Z]', password):
|
||||
issues.append("an uppercase letter")
|
||||
|
||||
if self.require_lowercase and not re.search(r'[a-z]', password):
|
||||
issues.append("a lowercase letter")
|
||||
|
||||
if self.require_digit and not re.search(r'[0-9]', password):
|
||||
issues.append("a number")
|
||||
|
||||
if self.require_special and not re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
|
||||
issues.append("a special character")
|
||||
|
||||
if issues:
|
||||
raise ValidationError(
|
||||
message=f"Password must contain: {', '.join(issues)}",
|
||||
cursor_position=len(password)
|
||||
)
|
||||
|
||||
|
||||
class APIKeyValidator(Validator):
|
||||
"""Validator for API key format"""
|
||||
|
||||
def validate(self, document):
|
||||
api_key = document.text
|
||||
|
||||
if len(api_key) == 0:
|
||||
raise ValidationError(
|
||||
message="API key is required",
|
||||
cursor_position=0
|
||||
)
|
||||
|
||||
if not (api_key.startswith('sk-') or api_key.startswith('pk-')):
|
||||
raise ValidationError(
|
||||
message='API key must start with "sk-" or "pk-"',
|
||||
cursor_position=len(api_key)
|
||||
)
|
||||
|
||||
if len(api_key) < 32:
|
||||
raise ValidationError(
|
||||
message="API key appears to be too short",
|
||||
cursor_position=len(api_key)
|
||||
)
|
||||
|
||||
|
||||
def calculate_password_strength(password):
|
||||
"""Calculate password strength score"""
|
||||
strength = 0
|
||||
|
||||
if len(password) >= 8:
|
||||
strength += 1
|
||||
if len(password) >= 12:
|
||||
strength += 1
|
||||
if re.search(r'[a-z]', password):
|
||||
strength += 1
|
||||
if re.search(r'[A-Z]', password):
|
||||
strength += 1
|
||||
if re.search(r'[0-9]', password):
|
||||
strength += 1
|
||||
if re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
|
||||
strength += 1
|
||||
|
||||
levels = ['Very Weak', 'Weak', 'Fair', 'Good', 'Strong', 'Very Strong']
|
||||
return levels[min(strength, len(levels) - 1)]
|
||||
|
||||
|
||||
def password_prompt_example():
|
||||
"""Example password prompts with validation"""
|
||||
|
||||
print("\n🔒 Password Prompt Example\n")
|
||||
|
||||
# Password with strength validation
|
||||
password = questionary.password(
|
||||
"Enter your password:",
|
||||
validate=PasswordStrengthValidator(min_length=8)
|
||||
).ask()
|
||||
|
||||
# Confirm password
|
||||
confirm_password = questionary.password(
|
||||
"Confirm your password:",
|
||||
validate=lambda text: text == password or "Passwords do not match"
|
||||
).ask()
|
||||
|
||||
print(f"\n✅ Password strength: {calculate_password_strength(password)}")
|
||||
|
||||
# API key input
|
||||
api_key = questionary.password(
|
||||
"Enter your API key:",
|
||||
validate=APIKeyValidator()
|
||||
).ask()
|
||||
|
||||
print(f"✅ API key format: {api_key[:6]}...")
|
||||
|
||||
# Optional encryption key
|
||||
encryption_key = questionary.password(
|
||||
"Enter encryption key (optional, press Enter to skip):",
|
||||
validate=lambda text: len(text) == 0 or len(text) >= 16 or "Encryption key must be at least 16 characters"
|
||||
).ask()
|
||||
|
||||
# Don't log actual passwords!
|
||||
answers = {
|
||||
'passwordSet': True,
|
||||
'passwordStrength': calculate_password_strength(password),
|
||||
'apiKeyPrefix': api_key[:6],
|
||||
'encryptionKeySet': len(encryption_key) > 0
|
||||
}
|
||||
|
||||
print("\n✅ Credentials received (not displayed for security)")
|
||||
import json
|
||||
print(json.dumps(answers, indent=2))
|
||||
|
||||
return answers
|
||||
|
||||
|
||||
def secure_account_setup():
|
||||
"""Example: Complete secure account setup"""
|
||||
|
||||
print("\n🔐 Secure Account Setup\n")
|
||||
|
||||
# Username
|
||||
username = questionary.text(
|
||||
"Username:",
|
||||
validate=lambda text: len(text) > 0 or "Username required"
|
||||
).ask()
|
||||
|
||||
# Strong password
|
||||
print("\n📝 Password requirements:")
|
||||
print(" • At least 12 characters")
|
||||
print(" • Uppercase and lowercase letters")
|
||||
print(" • Numbers")
|
||||
print(" • Special characters (!@#$%^&*)")
|
||||
print()
|
||||
|
||||
password = questionary.password(
|
||||
"Password:",
|
||||
validate=PasswordStrengthValidator(
|
||||
min_length=12,
|
||||
require_uppercase=True,
|
||||
require_lowercase=True,
|
||||
require_digit=True,
|
||||
require_special=True
|
||||
)
|
||||
).ask()
|
||||
|
||||
# Confirm password
|
||||
confirm = questionary.password(
|
||||
"Confirm password:",
|
||||
validate=lambda text: text == password or "Passwords do not match"
|
||||
).ask()
|
||||
|
||||
# Optional: Remember credentials
|
||||
remember = questionary.confirm(
|
||||
"Remember credentials? (stored securely)",
|
||||
default=False
|
||||
).ask()
|
||||
|
||||
strength = calculate_password_strength(password)
|
||||
|
||||
print(f"\n✅ Account created for: {username}")
|
||||
print(f"🔒 Password strength: {strength}")
|
||||
|
||||
if remember:
|
||||
print("💾 Credentials will be stored securely")
|
||||
|
||||
return {
|
||||
'username': username,
|
||||
'passwordStrength': strength,
|
||||
'remember': remember
|
||||
}
|
||||
|
||||
|
||||
def database_credentials_setup():
|
||||
"""Example: Database connection credentials"""
|
||||
|
||||
print("\n🗄️ Database Credentials Setup\n")
|
||||
|
||||
# Database username
|
||||
db_user = questionary.text(
|
||||
"Database username:",
|
||||
default="postgres",
|
||||
validate=lambda text: len(text) > 0 or "Username required"
|
||||
).ask()
|
||||
|
||||
# Database password
|
||||
db_password = questionary.password(
|
||||
"Database password:",
|
||||
validate=lambda text: len(text) >= 8 or "Password must be at least 8 characters"
|
||||
).ask()
|
||||
|
||||
# Admin password (if needed)
|
||||
is_admin = questionary.confirm(
|
||||
"Create admin user?",
|
||||
default=False
|
||||
).ask()
|
||||
|
||||
admin_password = None
|
||||
if is_admin:
|
||||
admin_password = questionary.password(
|
||||
"Admin password:",
|
||||
validate=PasswordStrengthValidator(min_length=12)
|
||||
).ask()
|
||||
|
||||
admin_confirm = questionary.password(
|
||||
"Confirm admin password:",
|
||||
validate=lambda text: text == admin_password or "Passwords do not match"
|
||||
).ask()
|
||||
|
||||
print(f"\n✅ Admin password strength: {calculate_password_strength(admin_password)}")
|
||||
|
||||
credentials = {
|
||||
'dbUser': db_user,
|
||||
'dbPasswordSet': True,
|
||||
'adminConfigured': is_admin
|
||||
}
|
||||
|
||||
print("\n✅ Database credentials configured")
|
||||
import json
|
||||
print(json.dumps(credentials, indent=2))
|
||||
|
||||
return credentials
|
||||
|
||||
|
||||
def api_token_setup():
|
||||
"""Example: API token and secret key setup"""
|
||||
|
||||
print("\n🔑 API Token Setup\n")
|
||||
|
||||
# API key
|
||||
api_key = questionary.password(
|
||||
"Enter API key:",
|
||||
validate=lambda text: len(text) > 0 or "API key required"
|
||||
).ask()
|
||||
|
||||
# Secret key
|
||||
secret_key = questionary.password(
|
||||
"Enter secret key:",
|
||||
validate=lambda text: len(text) >= 32 or "Secret key must be at least 32 characters"
|
||||
).ask()
|
||||
|
||||
# Webhook secret (optional)
|
||||
use_webhooks = questionary.confirm(
|
||||
"Configure webhook authentication?",
|
||||
default=False
|
||||
).ask()
|
||||
|
||||
webhook_secret = None
|
||||
if use_webhooks:
|
||||
webhook_secret = questionary.password(
|
||||
"Webhook secret:",
|
||||
validate=lambda text: len(text) >= 16 or "Webhook secret must be at least 16 characters"
|
||||
).ask()
|
||||
|
||||
# Environment
|
||||
environment = questionary.select(
|
||||
"Environment:",
|
||||
choices=['Development', 'Staging', 'Production']
|
||||
).ask()
|
||||
|
||||
config = {
|
||||
'apiKeySet': True,
|
||||
'secretKeySet': True,
|
||||
'webhookConfigured': use_webhooks,
|
||||
'environment': environment
|
||||
}
|
||||
|
||||
print("\n✅ API credentials configured")
|
||||
print(f"Environment: {environment}")
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def password_change_flow():
|
||||
"""Example: Password change with old password verification"""
|
||||
|
||||
print("\n🔄 Change Password\n")
|
||||
|
||||
# Old password (in real app, verify against stored hash)
|
||||
old_password = questionary.password(
|
||||
"Enter current password:",
|
||||
validate=lambda text: len(text) > 0 or "Current password required"
|
||||
).ask()
|
||||
|
||||
# New password
|
||||
new_password = questionary.password(
|
||||
"Enter new password:",
|
||||
validate=PasswordStrengthValidator(min_length=8)
|
||||
).ask()
|
||||
|
||||
# Ensure new password is different
|
||||
if new_password == old_password:
|
||||
print("\n❌ New password must be different from current password")
|
||||
return password_change_flow()
|
||||
|
||||
# Confirm new password
|
||||
confirm_password = questionary.password(
|
||||
"Confirm new password:",
|
||||
validate=lambda text: text == new_password or "Passwords do not match"
|
||||
).ask()
|
||||
|
||||
print(f"\n✅ Password changed successfully")
|
||||
print(f"🔒 New password strength: {calculate_password_strength(new_password)}")
|
||||
|
||||
return {'passwordChanged': True}
|
||||
|
||||
|
||||
def main():
|
||||
"""Run password prompt examples"""
|
||||
try:
|
||||
print("=== Password Prompt Examples ===")
|
||||
|
||||
# Example 1: Basic password prompts
|
||||
password_prompt_example()
|
||||
|
||||
# Example 2: Secure account setup
|
||||
secure_account_setup()
|
||||
|
||||
# Example 3: Database credentials
|
||||
database_credentials_setup()
|
||||
|
||||
# Example 4: API token setup
|
||||
api_token_setup()
|
||||
|
||||
# Example 5: Password change
|
||||
password_change_flow()
|
||||
|
||||
print("\n✅ Password prompt examples complete!")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n❌ User interrupted prompt")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n\n❌ Error: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
220
skills/inquirer-patterns/templates/python/text_prompt.py
Normal file
220
skills/inquirer-patterns/templates/python/text_prompt.py
Normal file
@@ -0,0 +1,220 @@
|
||||
"""
|
||||
Text Input Prompt Template
|
||||
|
||||
Use for: Names, emails, URLs, paths, free-form text
|
||||
Features: Validation, default values, transform
|
||||
"""
|
||||
|
||||
import questionary
|
||||
import re
|
||||
from questionary import ValidationError, Validator
|
||||
|
||||
|
||||
class UsernameValidator(Validator):
|
||||
"""Validate username format"""
|
||||
|
||||
def validate(self, document):
|
||||
text = document.text
|
||||
if len(text) == 0:
|
||||
raise ValidationError(
|
||||
message='Username is required',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
if len(text) < 3:
|
||||
raise ValidationError(
|
||||
message='Username must be at least 3 characters',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
if not re.match(r'^[a-zA-Z0-9_-]+$', text):
|
||||
raise ValidationError(
|
||||
message='Username can only contain letters, numbers, hyphens, and underscores',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
|
||||
|
||||
class EmailValidator(Validator):
|
||||
"""Validate email format"""
|
||||
|
||||
def validate(self, document):
|
||||
text = document.text
|
||||
email_regex = r'^[^\s@]+@[^\s@]+\.[^\s@]+$'
|
||||
if not re.match(email_regex, text):
|
||||
raise ValidationError(
|
||||
message='Invalid email address',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
|
||||
|
||||
class URLValidator(Validator):
|
||||
"""Validate URL format"""
|
||||
|
||||
def validate(self, document):
|
||||
text = document.text
|
||||
if len(text) == 0:
|
||||
return # Optional field
|
||||
url_regex = r'^https?://.+'
|
||||
if not re.match(url_regex, text):
|
||||
raise ValidationError(
|
||||
message='Must be a valid URL (http:// or https://)',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
|
||||
|
||||
class AgeValidator(Validator):
|
||||
"""Validate age range"""
|
||||
|
||||
def validate(self, document):
|
||||
text = document.text
|
||||
try:
|
||||
age = int(text)
|
||||
if age < 18:
|
||||
raise ValidationError(
|
||||
message='You must be at least 18 years old',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
if age > 120:
|
||||
raise ValidationError(
|
||||
message='Please enter a realistic age',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
except ValueError:
|
||||
raise ValidationError(
|
||||
message='Please enter a valid number',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
|
||||
|
||||
class BioValidator(Validator):
|
||||
"""Validate bio length"""
|
||||
|
||||
def validate(self, document):
|
||||
text = document.text
|
||||
if len(text) > 200:
|
||||
raise ValidationError(
|
||||
message='Bio must be 200 characters or less',
|
||||
cursor_position=len(text)
|
||||
)
|
||||
|
||||
|
||||
def text_prompt_example():
|
||||
"""Example text input prompts with validation"""
|
||||
|
||||
print("\n📝 Text Input Example\n")
|
||||
|
||||
# Username input
|
||||
username = questionary.text(
|
||||
"Enter your username:",
|
||||
validate=UsernameValidator
|
||||
).ask()
|
||||
|
||||
# Email input
|
||||
email = questionary.text(
|
||||
"Enter your email:",
|
||||
validate=EmailValidator
|
||||
).ask()
|
||||
|
||||
# Website input (optional)
|
||||
website = questionary.text(
|
||||
"Enter your website (optional):",
|
||||
default="",
|
||||
validate=URLValidator
|
||||
).ask()
|
||||
|
||||
# Age input with conversion
|
||||
age_str = questionary.text(
|
||||
"Enter your age:",
|
||||
validate=AgeValidator
|
||||
).ask()
|
||||
age = int(age_str)
|
||||
|
||||
# Bio input
|
||||
bio = questionary.text(
|
||||
"Enter a short bio:",
|
||||
validate=BioValidator,
|
||||
multiline=False
|
||||
).ask()
|
||||
|
||||
answers = {
|
||||
'username': username.lower(),
|
||||
'email': email,
|
||||
'website': website,
|
||||
'age': age,
|
||||
'bio': bio
|
||||
}
|
||||
|
||||
print("\n✅ Answers received:")
|
||||
import json
|
||||
print(json.dumps(answers, indent=2))
|
||||
|
||||
return answers
|
||||
|
||||
|
||||
# Alternative: Using lambda validators
|
||||
def lambda_validator_example():
|
||||
"""Example using lambda validators for simpler cases"""
|
||||
|
||||
print("\n📝 Lambda Validator Example\n")
|
||||
|
||||
# Simple required field
|
||||
name = questionary.text(
|
||||
"Name:",
|
||||
validate=lambda text: len(text) > 0 or "Name is required"
|
||||
).ask()
|
||||
|
||||
# Email validation
|
||||
email = questionary.text(
|
||||
"Email:",
|
||||
validate=lambda text: bool(re.match(r'^[^\s@]+@[^\s@]+\.[^\s@]+$', text)) or "Invalid email"
|
||||
).ask()
|
||||
|
||||
# Numeric validation
|
||||
port = questionary.text(
|
||||
"Port number:",
|
||||
default="8000",
|
||||
validate=lambda text: text.isdigit() and 1 <= int(text) <= 65535 or "Invalid port (1-65535)"
|
||||
).ask()
|
||||
|
||||
# Path validation
|
||||
path = questionary.text(
|
||||
"Project path:",
|
||||
default="./my-project",
|
||||
validate=lambda text: len(text) > 0 or "Path is required"
|
||||
).ask()
|
||||
|
||||
answers = {
|
||||
'name': name,
|
||||
'email': email,
|
||||
'port': int(port),
|
||||
'path': path
|
||||
}
|
||||
|
||||
print("\n✅ Answers received:")
|
||||
import json
|
||||
print(json.dumps(answers, indent=2))
|
||||
|
||||
return answers
|
||||
|
||||
|
||||
def main():
|
||||
"""Run text prompt examples"""
|
||||
try:
|
||||
print("=== Text Prompt Examples ===")
|
||||
|
||||
# Example 1: Class-based validators
|
||||
text_prompt_example()
|
||||
|
||||
# Example 2: Lambda validators
|
||||
lambda_validator_example()
|
||||
|
||||
print("\n✅ Text prompt examples complete!")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n❌ User interrupted prompt")
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n\n❌ Error: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user