Skip to main content

Prompts

The prompt function is the core of interactive archetype generation, enabling you to gather user input in various formats with validation and smart defaults.

Basic Prompting

Simple Text Input

// Simple text input
let name = prompt("Project name:");

// Store in context
context.service_name = prompt("Service name:");

Prompt with Configuration

context.service_suffix = prompt("Service Suffix:", #{
defaults_with: "Service", // Default value
min: 2, // Minimum length
max: 50, // Maximum length
placeholder: "Enter suffix", // Placeholder text
help: "Suffix for service class names",
optional: false, // Required field
answer_key: "service_suffix" // Key for answer lookup
});

Prompt Types

Integer Input

context.port = prompt("Server port:", #{
type: Int,
defaults_with: 8080,
min: 1024,
max: 65535,
help: "Port number between 1024-65535"
});

// Dynamic defaults based on other values
context.management_port = prompt("Management port:", #{
type: Int,
defaults_with: context.port + 1000,
min: 1024,
max: 65535
});

Boolean Input

context.enable_https = prompt("Enable HTTPS?", #{
type: Bool, // or Confirm
defaults_with: true
});

List Input

context.features = prompt("Features to include:", #{
type: List,
help: "Enter features one by one, empty to finish"
});

Selection Input

context.database = prompt("Database type:", #{
type: Select([
"postgresql",
"mysql",
"sqlite",
"mongodb"
]),
defaults_with: "postgresql"
});

MultiSelect Input

context.languages = prompt("Programming languages:", #{
type: MultiSelect([
"Rust",
"JavaScript",
"Python",
"Go",
"Java"
]),
defaults_with: ["Rust", "JavaScript"]
});

Editor Input

context.description = prompt("Detailed description:", #{
type: Editor,
defaults_with: "# Project Description\n\nDescribe your project here...",
help: "Opens your default editor for multi-line input"
});

Advanced Prompting Patterns

Conditional Prompting Logic

// Progressive prompting based on choices
let project_type = prompt("Project type:", #{
type: Select(["web", "cli", "library", "service"])
});

context.project_type = project_type;

// Type-specific prompts
if project_type == "web" {
context.framework = prompt("Web framework:", #{
type: Select(["react", "vue", "angular", "svelte"])
});

context.styling = prompt("Styling approach:", #{
type: Select(["css", "scss", "styled-components", "tailwind"])
});

} else if project_type == "cli" {
context.cli_framework = prompt("CLI framework:", #{
type: Select(["clap", "structopt", "argh"])
});

context.subcommands = prompt("Include subcommands?", #{
type: Bool,
defaults_with: true
});

} else if project_type == "service" {
context.api_type = prompt("API type:", #{
type: Select(["rest", "graphql", "grpc"])
});

context.database_required = prompt("Requires database?", #{
type: Bool
});

if context.database_required {
context.database_type = prompt("Database type:", #{
type: Select(["postgresql", "mysql", "mongodb", "sqlite"])
});
}
}

Feature Flag Management

// Collect features
let available_features = [
"authentication",
"authorization",
"logging",
"metrics",
"health-checks",
"database",
"caching",
"rate-limiting"
];

context.features = prompt("Select features:", #{
type: MultiSelect(available_features),
help: "Choose features to include in your service"
});

// Process feature dependencies
let selected_features = context.features;

// Auto-include dependencies
if "authentication" in selected_features && !("database" in selected_features) {
print("Authentication requires database - adding database feature");
selected_features.push("database");
}

if "metrics" in selected_features && !("health-checks" in selected_features) {
print("Metrics includes health checks - adding health-checks feature");
selected_features.push("health-checks");
}

context.features = selected_features;

// Set feature flags for templates
for feature in selected_features {
context["enable_" + snake_case(feature)] = true;
}

Data Validation

// Input validation
let validate_port = |port| {
if port < 1024 {
throw "Port must be >= 1024";
}
if port > 65535 {
throw "Port must be <= 65535";
}
return true;
};

// Validation in prompts
context.port = prompt("Server port:", #{
type: Int,
min: 1024,
max: 65535,
help: "Valid port range: 1024-65535"
});

// Manual validation
try {
validate_port(context.port);
print("Port validation passed");
} catch (error) {
print("Port validation failed: " + error);
// Could re-prompt or use default
context.port = 8080;
}

Complex Data Structures

// Build complex configuration
context.services = [];

let add_more = true;
while add_more {
let service = #{};

service.name = prompt("Service name:");
service.port = prompt("Service port:", #{
type: Int,
defaults_with: 8000 + context.services.len()
});

service.database = prompt("Requires database?", #{
type: Bool
});

if service.database {
service.database_type = prompt("Database type:", #{
type: Select(["postgresql", "mysql", "mongodb"])
});
}

context.services.push(service);

add_more = prompt("Add another service?", #{
type: Bool,
defaults_with: false
});
}

// Process services for template variables
context.service_count = context.services.len();
context.total_ports = context.services.len();
context.requires_database = false;

for service in context.services {
if service.database {
context.requires_database = true;
break;
}
}

Answer Sources and Pre-filled Data

Custom Answer Sources

// Custom answer source
let alternate_answers = #{
service_port: 9090,
database_type: "mongodb",
enable_auth: true
};

// Use alternate answers
context.port = prompt("Service port:", #{
type: Int,
answer_key: "service_port",
answer_source: alternate_answers
});

// Check for answers in render context
context.debug_enabled = prompt("Enable debug mode?", #{
type: Bool,
answer_key: "debug_mode", // Looks in current answers
defaults_with: false
});

Best Practices

Progressive Disclosure

Start with essential questions and progressively ask for more detailed configuration:

// Essential questions first
context.project_name = prompt("Project name:");
context.project_type = prompt("Project type:", #{
type: Select(["web", "api", "cli"])
});

// Then type-specific details
// ... conditional prompts based on project_type

// Finally, optional advanced configuration
let configure_advanced = prompt("Configure advanced options?", #{
type: Bool,
defaults_with: false
});

if configure_advanced {
// Advanced configuration prompts
}

Helpful Defaults and Context

// Use contextual defaults
context.app_port = prompt("Application port:", #{
type: Int,
defaults_with: switch context.app_type {
"web" => 3000,
"api" => 8080,
"development" => 3000,
_ => 8000
}
});

Clear Help Text

context.database_url = prompt("Database URL:", #{
help: "Connection string like postgresql://user:pass@host:5432/dbname",
placeholder: "postgresql://localhost:5432/myapp"
});

Case Transformations in Prompts

For comprehensive case transformation capabilities, see the reference documentation:

Quick Example

// Apply case transformations to prompt input
context += prompt("Service name:", "service", #{
cased_as: CasedKeyCasedValue("entity", [PascalCase, SnakeCase, KebabCase])
});

// Creates: entity_pascal_case, entity_snake_case, entity_kebab_case

Prompting vs Set

When to Use Prompting

  • User interaction: When you need user input or decisions
  • Configuration choices: When users select from available options
  • Optional settings: When users can provide custom values or use defaults
  • Validation required: When you need to validate and constrain user input
// Good use cases for prompting
let service_name = prompt("Service name:");
let database_type = prompt("Database:", #{
type: Select(["postgresql", "mysql", "sqlite"])
});
let enable_auth = prompt("Enable authentication?", #{
type: Bool,
defaults_with: true
});

When to Use Set

  • Programmatic assignment: When values are determined by logic, not user input
  • Derived values: When calculating values from other context variables
  • Case transformations: When you need multiple case variants of the same value
  • Batch operations: When setting multiple related variables efficiently
// Good use cases for set (see Set documentation for details)
context += set("api_version", "v" + context.version);
context += set("service_class", context.service_name, #{
cased_as: FixedIdentityCasedValue(PascalCase)
});

Combining Prompting and Set

// Get user input with prompt
let entity_name = prompt("Entity name:");

// Use set to create template variables
context += set("entity", entity_name, #{
cased_as: CasedIdentityCasedValue([PascalCase, SnakeCase, KebabCase])
});

For detailed information about programmatic variable assignment, see Set.

Next Steps

  • Learn about Set for programmatic variable assignment with case transformations
  • Learn about Case Styles for available transformation options
  • Explore Case Strategies for applying multiple transformations
  • Check Casing for comprehensive examples and patterns
  • Explore Rhai Basics for language fundamentals