Module :: unilang
A universal command framework that lets you define command-line interfaces once and deploy them across multiple interaction paradigms — CLI, TUI, GUI, Web APIs, and more.
Why unilang?
When building command-line tools, you often face these challenges:
- Repetitive Code: Defining argument parsing, validation, and help generation for each command
- Inconsistent APIs: Different interaction modes (CLI vs Web API) require separate implementations
- Limited Extensibility: Hard to add new commands or change existing ones without major refactoring
- Poor User Experience: Inconsistent help messages, error handling, and command organization
unilang solves these problems by providing:
- 📝 Single Definition: Define commands once, use everywhere
- 🔧 Multiple Modalities: Same commands work as CLI, Web API, or programmatic API
- 🏗️ Modular Architecture: Easy to add, modify, or remove commands
- 🎯 Type Safety: Strong typing with comprehensive validation
- 📚 Auto Documentation: Help text and command discovery built-in
- 🆘 Smart Help System: Three ways to get help (
.help,??,?) - always accessible - 🔍 Rich Validation: Built-in validators for common patterns
Quick Start
Installation
Basic Example
Here's a simple "Hello World" command:
use *;
Run this example:
# Try the help conventions:
Command Requirements
Important: All commands in unilang must follow explicit naming conventions:
- ✅ Dot Prefix Required: Commands must start with a dot (e.g.,
.greet,.math.add) - ❌ No Implicit Magic: Command names are used exactly as registered - no automatic transformations
- 🔧 Namespace Format: Use
.namespace.commandfor hierarchical organization - ⚡ Validation: Framework rejects commands that don't follow these rules
use CommandDefinition;
// ✅ Correct - explicit dot prefix
let cmd = CommandDefinition ;
// This would be rejected by validation
// let invalid_cmd = CommandDefinition {
// name: "greet".to_string(), // Missing dot prefix - ERROR!
// // ... other fields would be required too
// };
Core Concepts
1. Command Registry
The central hub that stores and manages all command definitions and their execution routines.
use *;
let mut registry = new;
// registry is now ready to use
2. Command Definition
Describes a command's metadata, arguments, and behavior.
use *;
let command = CommandDefinition
;
// command definition is complete
assert_eq!;
3. Argument Types
unilang supports rich argument types with automatic parsing and validation:
- Basic Types:
String,Integer,Float,Boolean - Path Types:
Path,File,Directory - Complex Types:
Url,DateTime,Pattern(regex) - Collections:
List<T>,Map<K,V> - Special Types:
Enum(choices),JsonString,Object
4. Validation Rules
Built-in validators ensure arguments meet requirements:
use *;
use ValidationRule;
let validation_rules : = vec!
;
assert_eq!;
5. Command Execution Pipeline
The execution flow: Parse → Validate → Execute
use *;
let registry = new;
let pipeline = new;
let result = pipeline.process_command_simple;
// result contains the execution outcome
6. Verbosity Control
Control debug output levels for cleaner CLI experiences:
use *;
use UnilangParserOptions;
// Create registry and set verbosity programmatically
let registry = new;
let mut parser_options = default;
parser_options.verbosity = 0; // 0 = quiet, 1 = normal, 2 = debug
let pipeline = with_parser_options;
Or use environment variable:
# Quiet mode - suppress all debug output
UNILANG_VERBOSITY=0
# Normal mode (default) - standard output only
UNILANG_VERBOSITY=1
# Debug mode - include parser traces
UNILANG_VERBOSITY=2
Examples
Working with Different Argument Types
use *;
use ValidationRule;
// See examples/02_argument_types.rs for the full example
let command = CommandDefinition
;
assert_eq!;
Run the argument types demo:
Using Collections
use *;
// See examples/03_collection_types.rs for the full example
// List of strings with custom delimiter
let _tags_arg = ArgumentDefinition
;
// Map with custom delimiters
let _options_arg = ArgumentDefinition
;
assert_eq!;
Run the collections demo:
Namespaces and Command Organization
use *;
// See examples/05_namespaces_and_aliases.rs for the full example
// Commands can be organized hierarchically
let commands = vec!
;
assert_eq!;
Loading Commands from YAML/JSON
// See examples/07_yaml_json_loading.rs for the full example
use ;
use *;
// Load from YAML file
let mut registry = new;
let commands = load_from_yaml_file?;
for cmd in commands
// Or from JSON string
let json = r#"[
{
"name" : "test",
"description" : "Test command",
"arguments" : []
}]"#;
let commands = load_from_json_str?;
Command-Line Usage Patterns
unilang supports flexible command-line syntax:
# Named arguments (recommended)
# Positional arguments
# Mixed (positional first, then named)
# With namespaces
# Using aliases
# List all commands (just dot)
# Get help for any command - multiple ways!
Advanced Features
Custom Validation
use *;
use ValidationRule;
// Create complex validation rules
let password_arg = ArgumentDefinition
;
assert!;
Batch Processing
use *;
let registry = new;
let pipeline = new;
// Process multiple commands efficiently
let commands = vec!
;
let batch_result = pipeline.process_batch;
// Success rate will be 0% since no commands are registered
assert_eq!;
Help System
unilang provides a comprehensive help system with three standardized ways to access help:
🔧 Automatic Help Generation
Every registered command automatically gets a .command.help counterpart:
use *;
let mut registry = new;
// Enable help conventions (enabled by default)
registry.enable_help_conventions;
// Register any command with auto-help enabled
let mut cmd = former
.name
.description
.end;
// Manually enable auto-help (builder method coming soon)
cmd.auto_help_enabled = true;
// Define a simple routine
let routine = Boxnew;
registry.register_with_auto_help?;
// Now BOTH commands are available:
// .greet - The original command
// .greet.help - Auto-generated help command
🎯 Three Help Access Methods
1. Traditional Help Operator (?)
2. Modern Help Parameter (??) - 🆕 Recommended
3. Dedicated Help Commands (.command.help) - 🆕 Auto-Generated
✨ Help Content Features
- Comprehensive: Arguments, validation rules, examples, aliases
- Consistent Formatting: Professional, hierarchical display
- Always Available: Never blocked by missing required arguments
- Auto-Discovery: Tab completion includes
.helpcommands
💡 Best Practices
- Use
??for interactive help during command construction - Use
.command.helpfor documentation and scripting - Traditional
?remains available for compatibility
This ensures users can always get help, even when they don't know the required arguments or command structure.
Full CLI Example
For a complete example showing all features, check out:
# Run the full CLI example with dot-prefixed command
# See available commands (just dot shows all commands with help)
# Explore the new help conventions:
# Try the help conventions demo:
API Modes
unilang can be used in different ways:
1. Pipeline API (Recommended)
High-level API that handles the full command execution pipeline:
use *;
let registry = new;
let pipeline = new;
let result = pipeline.process_command_simple;
// Result will indicate command not found since no commands are registered
assert!;
2. Component API
Lower-level access to individual components:
use *;
# let registry = new;
# let input = ".example";
# let mut context = default;
// Parse
let parser = new;
let instruction = parser.parse_single_instruction?;
// Analyze
let analyzer = new;
let commands = analyzer.analyze?;
// Execute
let interpreter = new;
interpreter.run?;
3. Direct Integration
For maximum control:
use *;
# let registry = new;
# let verified_command = todo!;
# let context = default;
// Direct command execution
let routine = registry.routines.get.unwrap;
let result = routine?;
REPL Features
Unilang provides two REPL modes designed for different use cases and environments:
Basic REPL (repl feature)
- Standard I/O: Works in any terminal environment
- Command History: Tracks executed commands for debugging
- Built-in Help: Integrated help system with
?operator - Cross-platform: Compatible with all supported platforms
- Lightweight: Minimal dependencies for embedded use cases
Enhanced REPL (enhanced_repl feature) ⭐ Enabled by Default
- 📋 Arrow Key Navigation: ↑/↓ for command history browsing
- ⚡ Tab Auto-completion: Command and argument completion
- 🔐 Interactive Input: Secure password/API key prompting with masked input
- 🧠 Advanced Error Recovery: Intelligent suggestions and contextual help
- 💾 Persistent Session: Command history saved across sessions
- 🖥️ Terminal Detection: Automatic fallback to basic REPL in non-interactive environments
- 🎨 Rich Display: Colorized output and formatted help (when supported)
Feature Comparison
| Capability | Basic REPL | Enhanced REPL |
|---|---|---|
| Command execution | ✅ | ✅ |
| Error handling | ✅ | ✅ |
Help system (?) |
✅ | ✅ |
| Arrow key history | ❌ | ✅ |
| Tab completion | ❌ | ✅ |
| Interactive prompts | Basic | Secure/Masked |
| Session persistence | ❌ | ✅ |
| Auto-fallback | N/A | ✅ |
| Dependencies | None | rustyline, atty |
Quick Start
Default (Enhanced REPL included):
[]
= "0.10" # Enhanced REPL enabled by default
Minimal dependencies (basic REPL only):
[]
= { = "0.10", = false, = ["enabled", "repl"] }
REPL (Read-Eval-Print Loop) Support
unilang provides comprehensive support for building interactive REPL applications. The framework's stateless architecture makes it ideal for REPL implementations.
Basic REPL Implementation
use ;
use ;
Interactive Arguments with Secure Input
unilang supports interactive arguments for secure input like passwords:
// In your command definition
use ;
ArgumentDefinition ;
// In your REPL loop
use ;
match result.error
Advanced REPL Features
For production REPL applications, consider these patterns:
Command History & Auto-completion:
use HashMap;
let mut command_history = Vecnew;
let mut session_stats = new;
// In your REPL loop
if input.ends_with
command_history.push;
Error Recovery:
match result.error
Session Management:
// Track session statistics for debugging and UX
let mut session = ReplSession ;
session.command_count += 1;
if result.success else
REPL Performance Considerations
- Component Reuse: Pipeline components are stateless and reusable - this provides 20-50% performance improvement over creating new instances
- Memory Management: Bound command history to prevent memory leaks in long-running sessions
- Static Commands: Use static command registry with PHF for zero-cost lookups even with millions of commands
Complete REPL Examples
The examples/ directory contains comprehensive REPL implementations:
12_repl_loop.rs- Basic REPL with stateless operation15_interactive_repl_mode.rs- Interactive arguments and secure input17_advanced_repl_features.rs- Full-featured REPL with history, auto-completion, and error recovery
Key REPL Insights:
- ✅ Stateless Design: Each command execution is independent - no state accumulation
- ✅ Interactive Security: Proper handling of passwords and API keys
- ✅ Error Isolation: Command failures don't affect subsequent commands
- ✅ Memory Efficiency: Constant memory usage regardless of session length
- ✅ Professional UX: History, auto-completion, and intelligent error recovery
REPL Migration Guide
From Basic to Enhanced REPL
Step 1: Update your Cargo.toml
# If you currently use basic REPL:
= { = "0.10", = false, = ["enabled", "repl"] }
# Change to default (Enhanced REPL included):
= "0.10"
# Or explicitly enable enhanced REPL:
= { = "0.10", = ["enhanced_repl"] }
Step 2: Feature Detection in Code
Step 3: Handling Interactive Arguments Enhanced REPL provides better support for interactive arguments:
use *;
Migration Checklist
- Updated
Cargo.tomlwithenhanced_replfeature - Added feature-gated code for both REPL modes
- Updated interactive argument handling
- Tested both enhanced and basic REPL modes
- Updated error handling for better UX
Backward Compatibility
The enhanced REPL automatically falls back to basic functionality when:
- Running in non-interactive environments (pipes, redirects)
- Terminal capabilities are limited
- Dependencies are unavailable
Your existing REPL code will continue to work unchanged.
Error Handling
unilang provides comprehensive error handling:
use *;
let registry = new;
let pipeline = new;
let input = ".example";
match pipeline.process_command_simple
More Examples
Explore the examples/ directory for more detailed examples:
01_basic_command_registration.rs- Getting started02_argument_types.rs- All supported argument types03_collection_types.rs- Lists and maps04_validation_rules.rs- Input validation05_namespaces_and_aliases.rs- Command organization06_help_system.rs- Automatic help generation07_yaml_json_loading.rs- Loading commands from files18_help_conventions_demo.rs- 🆕 Help Conventions - Demo of.helpand??features08_semantic_analysis_simple.rs- Understanding the analysis phase09_command_execution.rs- Execution patterns10_full_pipeline.rs- Complete pipeline example11_pipeline_api.rs- Pipeline API featuresfull_cli_example.rs- Full-featured CLI applicationexamples/wasm-repl/- 🌐 WebAssembly REPL - Interactive web-based command interface
🌐 WebAssembly Support
UniLang provides full WebAssembly compatibility allowing you to run your command framework in web browsers with near-native performance.
Features
- 🚀 Complete Framework: Full unilang functionality in WebAssembly
- 🔧 Cross-Platform: Same API works in native and browser environments
- ⚡ SIMD Optimized: Fast parsing with SIMD acceleration where available
- 📦 Optimized Builds: Small bundle size (~800KB-1.2MB compressed)
- 🎯 Type Safety: Full type validation and error handling in WASM
- 🔄 Seamless Integration: Easy Rust-to-JavaScript bridge
Quick Start
-
Navigate to WASM REPL Example
-
Build for WebAssembly
# Option 1: Using wasm-pack (recommended) # Option 2: Using cargo directly -
Serve and Test
# Open http://localhost:8000 in your browser
Live Demo Commands
Try these commands in the WebAssembly REPL:
WebAssembly-Specific Features
- Conditional Compilation: Filesystem operations gracefully disabled for WASM targets
- Memory Optimization: Custom allocator (
wee_alloc) for reduced binary size - Error Handling: Browser-friendly panic hooks and error reporting
- Performance: SIMD acceleration for parsing and JSON processing
- Browser API Integration: Full access to Web APIs through
web-sys
For complete build and deployment instructions, see examples/wasm-repl/BUILD_GUIDE.md.
Contributing
See CONTRIBUTING.md for details.
License
Licensed under MIT license (LICENSE or https://opensource.org/licenses/MIT)