major changes
- Added documentation via mdbook - Created basic VS code extension - Implemented if else blocks and changed some syntax - fixed some issues
This commit is contained in:
2
docs/.gitignore
vendored
Normal file
2
docs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
book
|
||||
docs/book/
|
||||
14
docs/book.toml
Normal file
14
docs/book.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[book]
|
||||
authors = ["tototomate123"]
|
||||
language = "en"
|
||||
src = "src"
|
||||
title = "Rush Documentation"
|
||||
description = "Documentation for the Rush experimental scripting language"
|
||||
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/yourusername/rush"
|
||||
edit-url-template = "https://github.com/yourusername/rush/edit/main/docs/{path}"
|
||||
|
||||
[output.html.playground]
|
||||
editable = false
|
||||
copyable = true
|
||||
24
docs/src/SUMMARY.md
Normal file
24
docs/src/SUMMARY.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Summary
|
||||
|
||||
[Introduction](./introduction.md)
|
||||
|
||||
# Getting Started
|
||||
|
||||
- [Installation](./getting-started/installation.md)
|
||||
- [Quick Start](./getting-started/quick-start.md)
|
||||
|
||||
# Language Guide
|
||||
|
||||
- [Variables](./language/variables.md)
|
||||
- [Control Flow](./language/control-flow.md)
|
||||
- [Loops](./language/loops.md)
|
||||
- [Parallel Execution](./language/parallel.md)
|
||||
- [Built-in Variables](./language/builtins.md)
|
||||
|
||||
# Examples
|
||||
|
||||
- [Web Deployment](./examples/web-deploy.md)
|
||||
- [System Maintenance](./examples/system-maintenance.md)
|
||||
- [Data Pipeline](./examples/data-pipeline.md)
|
||||
- [CI/CD Pipeline](./examples/ci-pipeline.md)
|
||||
- [Database Backup](./examples/db-backup.md)
|
||||
65
docs/src/examples/ci-pipeline.md
Normal file
65
docs/src/examples/ci-pipeline.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# CI/CD Pipeline
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
Continuous Integration/Deployment pipeline with parallel testing.
|
||||
|
||||
## Script
|
||||
|
||||
See `/examples/ci_pipeline.rsh` in the repository.
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
PROJECT = "my-rust-app"
|
||||
BRANCH = "main"
|
||||
BUILD_ID = "build-12345"
|
||||
|
||||
echo "=== CI/CD Pipeline ==="
|
||||
echo "Project: $PROJECT"
|
||||
|
||||
# Environment validation
|
||||
if $IS_ROOT {
|
||||
echo "ERROR: Do not run CI/CD pipeline as root"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build stages (sequential)
|
||||
for stage in checkout lint test build package {
|
||||
echo "[$BUILD_ID] Stage: $stage"
|
||||
if $stage {
|
||||
echo "[$BUILD_ID] ✓ $stage completed"
|
||||
}
|
||||
}
|
||||
|
||||
# Run tests in parallel
|
||||
parallel {
|
||||
run {
|
||||
echo "[unit-tests] Running unit tests..."
|
||||
echo "[unit-tests] 127 tests passed"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[integration-tests] Running integration tests..."
|
||||
echo "[integration-tests] 45 tests passed"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[lint-check] Running cargo clippy..."
|
||||
echo "[lint-check] No warnings found"
|
||||
}
|
||||
}
|
||||
|
||||
# Multi-environment deployment
|
||||
for env in dev staging prod {
|
||||
DEPLOY_URL = "https://$PROJECT.$env.example.com"
|
||||
echo "[$env] Deployment target: $DEPLOY_URL"
|
||||
}
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **Security check**: Refuse to run as root
|
||||
- **Sequential build**: Steps that depend on each other
|
||||
- **Parallel tests**: Independent test suites run simultaneously
|
||||
- **Multi-environment deployment**: Same code deployed to different environments
|
||||
52
docs/src/examples/data-pipeline.md
Normal file
52
docs/src/examples/data-pipeline.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Data Pipeline
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
Data processing pipeline showing how to process multiple batches in parallel.
|
||||
|
||||
## Script
|
||||
|
||||
See `/examples/data_pipeline.rsh` in the repository.
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
DATASET = "user_analytics"
|
||||
INPUT_DIR = "$HOME/data/raw"
|
||||
OUTPUT_DIR = "$HOME/data/processed"
|
||||
BATCH_SIZE = "1000"
|
||||
|
||||
echo "Data Processing Pipeline: $DATASET"
|
||||
|
||||
# Pre-processing stages
|
||||
for stage in validate clean normalize {
|
||||
STAGE_UPPER = "$stage"
|
||||
echo " Stage: $STAGE_UPPER"
|
||||
}
|
||||
|
||||
# Process batches in parallel
|
||||
BATCH_1_IN = "$INPUT_DIR/batch_001.csv"
|
||||
BATCH_1_OUT = "$OUTPUT_DIR/batch_001.json"
|
||||
# ... (define other batches)
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo "[batch_001] Processing $BATCH_1_IN -> $BATCH_1_OUT"
|
||||
echo "[batch_001] Transformed 1000 records"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[batch_002] Processing $BATCH_2_IN -> $BATCH_2_OUT"
|
||||
echo "[batch_002] Transformed 1000 records"
|
||||
}
|
||||
# ... (more batches)
|
||||
}
|
||||
|
||||
echo "All batches processed successfully"
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **Parallel data processing**: Process multiple batches simultaneously
|
||||
- **Path construction**: Building input/output file paths
|
||||
- **Pipeline stages**: Sequential setup, parallel processing, sequential summary
|
||||
72
docs/src/examples/db-backup.md
Normal file
72
docs/src/examples/db-backup.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Database Backup
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
Database backup automation with validation and integrity checks.
|
||||
|
||||
## Script
|
||||
|
||||
See `/examples/db_backup.rsh` in the repository.
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
DB_NAME = "production_db"
|
||||
DB_HOST = "db.example.com"
|
||||
BACKUP_ROOT = "/backups/databases"
|
||||
BACKUP_PATH = "$BACKUP_ROOT/$DB_NAME"
|
||||
TIMESTAMP = "2024-01-15-143022"
|
||||
BACKUP_FILE = "$BACKUP_PATH/backup-$TIMESTAMP.sql.gz"
|
||||
|
||||
echo "Database Backup Script"
|
||||
|
||||
# Permission check
|
||||
if not $IS_ROOT {
|
||||
echo "Warning: Running as $USER (not root)"
|
||||
echo "Ensure $USER has database access"
|
||||
}
|
||||
|
||||
# Pre-backup validation
|
||||
for check in connectivity disk_space permissions {
|
||||
echo " Checking $check..."
|
||||
if $check {
|
||||
echo " ✓ $check OK"
|
||||
}
|
||||
}
|
||||
|
||||
# Backup stages
|
||||
for stage in dump compress encrypt verify {
|
||||
STAGE_FILE = "$BACKUP_PATH/$stage.tmp"
|
||||
echo "[$stage] Processing..."
|
||||
if $stage {
|
||||
echo "[$stage] ✓ Complete"
|
||||
}
|
||||
}
|
||||
|
||||
# Parallel integrity verification
|
||||
parallel {
|
||||
run {
|
||||
echo "[checksum] Computing SHA256..."
|
||||
echo "[checksum] a1b2c3d4e5f6..."
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[compression] Verifying gzip integrity..."
|
||||
echo "[compression] OK"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[restore-test] Testing restore on sample..."
|
||||
echo "[restore-test] Restore successful"
|
||||
}
|
||||
}
|
||||
|
||||
echo "Backup completed successfully!"
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **Pre-flight validation**: Check prerequisites before starting
|
||||
- **Multi-stage processing**: Sequential backup pipeline
|
||||
- **Parallel verification**: Simultaneously verify different aspects
|
||||
- **Comprehensive reporting**: Clear status messages throughout
|
||||
51
docs/src/examples/system-maintenance.md
Normal file
51
docs/src/examples/system-maintenance.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# System Maintenance
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
Example system maintenance script demonstrating permission checks, environment variables, and log rotation.
|
||||
|
||||
## Script
|
||||
|
||||
See the full script in `/examples/system_maintenance.rsh` in the repository.
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
HOSTNAME = "prod-server-01"
|
||||
MAX_DISK_USAGE = "85"
|
||||
LOG_DIR = "/var/log"
|
||||
BACKUP_DIR = "$HOME/backups"
|
||||
|
||||
echo "System Maintenance Script"
|
||||
echo "Running on: $HOSTNAME"
|
||||
echo "User: $USER"
|
||||
|
||||
# Permission-aware execution
|
||||
if $IS_ROOT {
|
||||
echo "Running with root privileges"
|
||||
|
||||
for check in disk memory services {
|
||||
echo "Checking $check status..."
|
||||
if $check {
|
||||
echo " ✓ $check is healthy"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "Running as $USER (limited permissions)"
|
||||
echo "Some checks may be skipped"
|
||||
}
|
||||
|
||||
# Log rotation planning
|
||||
echo "Preparing log rotation in $LOG_DIR"
|
||||
|
||||
for days in 1 7 30 {
|
||||
LOG_ARCHIVE = "$BACKUP_DIR/logs-$days-days-old.tar.gz"
|
||||
echo "Would archive logs older than $days days to $LOG_ARCHIVE"
|
||||
}
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **Permission-aware execution**: Different behavior for root vs normal user
|
||||
- **String interpolation**: Building paths with `$HOME`, `$USER`
|
||||
- **Loops for maintenance tasks**: Iterating over checks and retention periods
|
||||
184
docs/src/examples/web-deploy.md
Normal file
184
docs/src/examples/web-deploy.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Web Deployment
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
This example demonstrates a web application deployment pipeline using Rush's parallel execution capabilities.
|
||||
|
||||
## Full Script
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
# Web deployment pipeline example
|
||||
# Shows conditional logic, loops, and parallel execution
|
||||
|
||||
APP_NAME = "my-app"
|
||||
VERSION = "1.2.3"
|
||||
ENV = "staging"
|
||||
DEPLOY_DIR = "/var/www/$APP_NAME"
|
||||
BUILD_DIR = "./dist"
|
||||
|
||||
echo "Starting deployment for $APP_NAME v$VERSION to $ENV"
|
||||
|
||||
# Check prerequisites
|
||||
if not $IS_ROOT {
|
||||
echo "Warning: Not running as root. Some operations may fail."
|
||||
}
|
||||
|
||||
# Build steps
|
||||
STEPS = "lint test build"
|
||||
for step in lint test build {
|
||||
echo "[$step] Running..."
|
||||
|
||||
if $step {
|
||||
# Simulate the build step
|
||||
echo "[$step] Complete"
|
||||
}
|
||||
}
|
||||
|
||||
# Deploy in parallel
|
||||
echo "Deploying to multiple servers..."
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo "Server 1: Syncing files to web-1.$ENV.example.com"
|
||||
echo "Server 1: Deployment complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Server 2: Syncing files to web-2.$ENV.example.com"
|
||||
echo "Server 2: Deployment complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Server 3: Syncing files to web-3.$ENV.example.com"
|
||||
echo "Server 3: Deployment complete"
|
||||
}
|
||||
}
|
||||
|
||||
echo "All servers updated with $APP_NAME v$VERSION"
|
||||
|
||||
# Post-deployment checks
|
||||
for server in web-1 web-2 web-3 {
|
||||
FULL_HOST = "$server.$ENV.example.com"
|
||||
echo "Health check: $FULL_HOST - OK"
|
||||
}
|
||||
|
||||
echo "Deployment complete!"
|
||||
```
|
||||
|
||||
## Features Demonstrated
|
||||
|
||||
### 1. Configuration Variables
|
||||
|
||||
The script starts by defining configuration:
|
||||
|
||||
```rush
|
||||
APP_NAME = "my-app"
|
||||
VERSION = "1.2.3"
|
||||
ENV = "staging"
|
||||
DEPLOY_DIR = "/var/www/$APP_NAME"
|
||||
```
|
||||
|
||||
These variables are used throughout the script, making it easy to adapt for different applications.
|
||||
|
||||
### 2. Permission Check
|
||||
|
||||
```rush
|
||||
if not $IS_ROOT {
|
||||
echo "Warning: Not running as root. Some operations may fail."
|
||||
}
|
||||
```
|
||||
|
||||
The script warns if not running as root, but continues anyway (since deployment might work without root depending on file permissions).
|
||||
|
||||
### 3. Sequential Build Steps
|
||||
|
||||
```rush
|
||||
for step in lint test build {
|
||||
echo "[$step] Running..."
|
||||
|
||||
if $step {
|
||||
echo "[$step] Complete"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Build steps run sequentially since each step depends on the previous one completing successfully.
|
||||
|
||||
### 4. Parallel Server Deployment
|
||||
|
||||
```rush
|
||||
parallel {
|
||||
run {
|
||||
echo "Server 1: Syncing files to web-1.$ENV.example.com"
|
||||
echo "Server 1: Deployment complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Server 2: Syncing files to web-2.$ENV.example.com"
|
||||
echo "Server 2: Deployment complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Server 3: Syncing files to web-3.$ENV.example.com"
|
||||
echo "Server 3: Deployment complete"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Servers are updated in parallel since they're independent. This saves significant time vs deploying sequentially.
|
||||
|
||||
### 5. Post-Deployment Verification
|
||||
|
||||
```rush
|
||||
for server in web-1 web-2 web-3 {
|
||||
FULL_HOST = "$server.$ENV.example.com"
|
||||
echo "Health check: $FULL_HOST - OK"
|
||||
}
|
||||
```
|
||||
|
||||
After deployment, verify each server is healthy.
|
||||
|
||||
## Example Output
|
||||
|
||||
```
|
||||
Starting deployment for my-app v1.2.3 to staging
|
||||
Warning: Not running as root. Some operations may fail.
|
||||
[lint] Running...
|
||||
[lint] Complete
|
||||
[test] Running...
|
||||
[test] Complete
|
||||
[build] Running...
|
||||
[build] Complete
|
||||
Deploying to multiple servers...
|
||||
Server 1: Syncing files to web-1.staging.example.com
|
||||
Server 2: Syncing files to web-2.staging.example.com
|
||||
Server 3: Syncing files to web-3.staging.example.com
|
||||
Server 1: Deployment complete
|
||||
Server 2: Deployment complete
|
||||
Server 3: Deployment complete
|
||||
All servers updated with my-app v1.2.3
|
||||
Health check: web-1.staging.example.com - OK
|
||||
Health check: web-2.staging.example.com - OK
|
||||
Health check: web-3.staging.example.com - OK
|
||||
Deployment complete!
|
||||
```
|
||||
|
||||
Note: Output from parallel tasks may be interleaved.
|
||||
|
||||
## Adapting for Your Use
|
||||
|
||||
To use this for real deployments:
|
||||
|
||||
1. **Change configuration variables** to match your app
|
||||
2. **Replace echo with actual commands** (rsync, scp, etc.)
|
||||
3. **Add error handling** (check command exit codes)
|
||||
4. **Customize server list** for your infrastructure
|
||||
5. **Add real health checks** (curl, wget, etc.)
|
||||
|
||||
## Related
|
||||
|
||||
- [Parallel Execution](../language/parallel.md) - Learn more about parallel blocks
|
||||
- [Loops](../language/loops.md) - Sequential iteration patterns
|
||||
- [Variables](../language/variables.md) - Working with configuration
|
||||
72
docs/src/getting-started/installation.md
Normal file
72
docs/src/getting-started/installation.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Installation
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Rush is written in Rust, so you'll need:
|
||||
- Rust toolchain (rustc, cargo)
|
||||
- Git (to clone the repository)
|
||||
|
||||
## Installing Rust
|
||||
|
||||
If you don't have Rust installed, get it from [rustup.rs](https://rustup.rs/):
|
||||
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
## Building Rush
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/yourusername/rush.git
|
||||
cd rush
|
||||
```
|
||||
|
||||
2. Build the project:
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
3. The binary will be available at `./target/release/rush`
|
||||
|
||||
## Optional: Install System-Wide
|
||||
|
||||
To make Rush available system-wide:
|
||||
|
||||
```bash
|
||||
cargo install --path .
|
||||
```
|
||||
|
||||
This installs Rush to `~/.cargo/bin/rush` (make sure `~/.cargo/bin` is in your PATH).
|
||||
|
||||
## Verifying Installation
|
||||
|
||||
Test your installation:
|
||||
|
||||
```bash
|
||||
./target/release/rush --version
|
||||
# or if installed system-wide:
|
||||
rush --version
|
||||
```
|
||||
|
||||
Create a test script `hello.rsh`:
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
NAME = "World"
|
||||
echo "Hello, $NAME!"
|
||||
```
|
||||
|
||||
Make it executable and run it:
|
||||
```bash
|
||||
chmod +x hello.rsh
|
||||
./target/release/rush hello.rsh
|
||||
```
|
||||
|
||||
You should see: `Hello, World!`
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that Rush is installed, proceed to the [Quick Start](./quick-start.md) guide.
|
||||
172
docs/src/getting-started/quick-start.md
Normal file
172
docs/src/getting-started/quick-start.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# Quick Start
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
This guide will walk you through creating your first Rush script.
|
||||
|
||||
## Your First Script
|
||||
|
||||
Create a file called `hello.rsh`:
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
# Variables are assigned with =
|
||||
NAME = "Rush"
|
||||
echo "Hello from $NAME!"
|
||||
```
|
||||
|
||||
Run it:
|
||||
```bash
|
||||
rush hello.rsh
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
Hello from Rush!
|
||||
```
|
||||
|
||||
## Variables and Interpolation
|
||||
|
||||
Variables are automatically interpolated in strings:
|
||||
|
||||
```rush
|
||||
PROJECT = "my-app"
|
||||
VERSION = "1.0.0"
|
||||
FULL_NAME = "$PROJECT-v$VERSION"
|
||||
|
||||
echo "Building $FULL_NAME"
|
||||
# Output: Building my-app-v1.0.0
|
||||
```
|
||||
|
||||
## Using Built-in Variables
|
||||
|
||||
Rush provides several built-in variables:
|
||||
|
||||
```rush
|
||||
echo "Current user: $USER"
|
||||
echo "Home directory: $HOME"
|
||||
|
||||
if $IS_ROOT {
|
||||
echo "Running as root"
|
||||
} else {
|
||||
echo "Running as normal user"
|
||||
}
|
||||
```
|
||||
|
||||
## Conditional Logic
|
||||
|
||||
Use `if`/`else` for branching:
|
||||
|
||||
```rush
|
||||
ENV = "production"
|
||||
|
||||
if $ENV {
|
||||
echo "Environment: $ENV"
|
||||
}
|
||||
|
||||
if not $IS_ROOT {
|
||||
echo "Warning: Not running as root"
|
||||
} else {
|
||||
echo "Running with elevated privileges"
|
||||
}
|
||||
```
|
||||
|
||||
## Loops
|
||||
|
||||
Iterate over items with `for`:
|
||||
|
||||
```rush
|
||||
# Loop over space-separated items
|
||||
for name in Alice Bob Charlie {
|
||||
echo "Hello, $name!"
|
||||
}
|
||||
|
||||
# Use variables in loops
|
||||
SERVERS = "web-1 web-2 web-3"
|
||||
for server in web-1 web-2 web-3 {
|
||||
echo "Deploying to $server"
|
||||
}
|
||||
```
|
||||
|
||||
## Parallel Execution
|
||||
|
||||
Run tasks concurrently:
|
||||
|
||||
```rush
|
||||
parallel {
|
||||
run {
|
||||
echo "Task 1: Starting..."
|
||||
echo "Task 1: Complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Task 2: Starting..."
|
||||
echo "Task 2: Complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Task 3: Starting..."
|
||||
echo "Task 3: Complete"
|
||||
}
|
||||
}
|
||||
|
||||
echo "All tasks finished"
|
||||
```
|
||||
|
||||
The output from parallel blocks may be interleaved since they run concurrently.
|
||||
|
||||
## A Complete Example
|
||||
|
||||
Here's a more complete script showing multiple features:
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
# Configuration
|
||||
PROJECT = "web-app"
|
||||
ENV = "staging"
|
||||
DEPLOY_DIR = "/var/www/$PROJECT"
|
||||
|
||||
echo "Deployment Script for $PROJECT"
|
||||
echo "Environment: $ENV"
|
||||
echo ""
|
||||
|
||||
# Pre-flight checks
|
||||
if not $IS_ROOT {
|
||||
echo "Warning: Not root. Some operations may fail."
|
||||
}
|
||||
|
||||
# Build steps
|
||||
echo "Running build steps:"
|
||||
for step in lint test build {
|
||||
echo " - $step"
|
||||
}
|
||||
|
||||
# Deploy to multiple servers in parallel
|
||||
echo ""
|
||||
echo "Deploying to $ENV servers..."
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo "[server-1] Deploying $PROJECT"
|
||||
echo "[server-1] Complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[server-2] Deploying $PROJECT"
|
||||
echo "[server-2] Complete"
|
||||
}
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo "Deployment complete!"
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
Learn more about Rush's features:
|
||||
- [Variables](../language/variables.md) - Deep dive into variable handling
|
||||
- [Control Flow](../language/control-flow.md) - Conditionals and branching
|
||||
- [Loops](../language/loops.md) - Iteration patterns
|
||||
- [Parallel Execution](../language/parallel.md) - Concurrency in Rush
|
||||
85
docs/src/introduction.md
Normal file
85
docs/src/introduction.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Rush Documentation
|
||||
|
||||
Welcome to the Rush programming language documentation!
|
||||
|
||||
> ⚠️ **AI-Generated Documentation Notice**
|
||||
>
|
||||
> This documentation has been primarily generated by AI and may contain errors, inconsistencies, or incomplete information. Rush is an experimental project and is **not recommended for production use** at this time.
|
||||
>
|
||||
> If you find issues or have suggestions, please contribute to improving this documentation.
|
||||
|
||||
## What is Rush?
|
||||
|
||||
Rush is an experimental shell scripting language that combines:
|
||||
|
||||
- **Simple syntax** inspired by modern scripting languages
|
||||
- **Strict validation** to catch errors at parse time
|
||||
- **Built-in concurrency** with parallel execution blocks
|
||||
- **Type-aware variables** with automatic interpolation
|
||||
- **Control flow** familiar to programmers (if/else, for loops)
|
||||
|
||||
## Key Features
|
||||
|
||||
### Variable Interpolation
|
||||
Variables are automatically expanded in strings:
|
||||
```rush
|
||||
PROJECT = "my-app"
|
||||
DIR = "$HOME/projects/$PROJECT"
|
||||
echo $DIR # Outputs: /home/user/projects/my-app
|
||||
```
|
||||
|
||||
### Parallel Execution
|
||||
Run tasks concurrently with ease:
|
||||
```rush
|
||||
parallel {
|
||||
run { echo "Task 1" }
|
||||
run { echo "Task 2" }
|
||||
run { echo "Task 3" }
|
||||
}
|
||||
```
|
||||
|
||||
### Strict Validation
|
||||
Rush validates your scripts before execution:
|
||||
- Variables must be defined before use
|
||||
- Syntax errors are caught immediately
|
||||
- Clear error messages guide you to fixes
|
||||
|
||||
### Built-in Variables
|
||||
Access system information easily:
|
||||
- `$USER` - Current username
|
||||
- `$HOME` - Home directory
|
||||
- `$IS_ROOT` - Whether running as root
|
||||
|
||||
## Project Status
|
||||
|
||||
Rush is in **early experimental development**. The language design and implementation are subject to change. Current capabilities include:
|
||||
|
||||
- ✅ Variable assignment and interpolation
|
||||
- ✅ Conditional execution (if/else)
|
||||
- ✅ For loops
|
||||
- ✅ Parallel execution blocks
|
||||
- ✅ Basic built-in commands (echo, exit, require_root)
|
||||
- ⚠️ Limited external command support
|
||||
- ❌ No package management
|
||||
- ❌ No module system
|
||||
- ❌ Limited error handling
|
||||
|
||||
## Use Cases
|
||||
|
||||
Rush is designed for:
|
||||
- **Learning** parallel programming concepts
|
||||
- **Experimenting** with shell script alternatives
|
||||
- **Prototyping** automation workflows
|
||||
- **Exploring** strict validation in scripting languages
|
||||
|
||||
**Not recommended for:**
|
||||
- Production systems
|
||||
- Critical automation
|
||||
- Enterprise deployments
|
||||
- Anything requiring stability
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Installation](./getting-started/installation.md) - Get Rush set up
|
||||
- [Quick Start](./getting-started/quick-start.md) - Your first Rush script
|
||||
- [Language Guide](./language/variables.md) - Learn Rush syntax
|
||||
282
docs/src/language/builtins.md
Normal file
282
docs/src/language/builtins.md
Normal file
@@ -0,0 +1,282 @@
|
||||
# Built-in Variables
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
Rush provides several built-in variables that give you access to system information.
|
||||
|
||||
## Available Built-ins
|
||||
|
||||
### `$USER`
|
||||
|
||||
The current username.
|
||||
|
||||
```rush
|
||||
echo "Running as: $USER"
|
||||
# Output: Running as: alice
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Logging who ran a script
|
||||
- User-specific configuration
|
||||
- Checking if running as a specific user
|
||||
|
||||
```rush
|
||||
EXPECTED_USER = "deploy"
|
||||
|
||||
if not $USER {
|
||||
echo "ERROR: USER not set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Script executed by: $USER"
|
||||
```
|
||||
|
||||
### `$HOME`
|
||||
|
||||
The current user's home directory.
|
||||
|
||||
```rush
|
||||
echo "Home directory: $HOME"
|
||||
# Output: Home directory: /home/alice
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Building paths to user files
|
||||
- Configuration file locations
|
||||
- User-specific data directories
|
||||
|
||||
```rush
|
||||
CONFIG_DIR = "$HOME/.config/myapp"
|
||||
DATA_DIR = "$HOME/.local/share/myapp"
|
||||
CACHE_DIR = "$HOME/.cache/myapp"
|
||||
|
||||
echo "Configuration: $CONFIG_DIR"
|
||||
echo "Data: $DATA_DIR"
|
||||
echo "Cache: $CACHE_DIR"
|
||||
```
|
||||
|
||||
### `$IS_ROOT`
|
||||
|
||||
Boolean indicating if the script is running as root (UID 0).
|
||||
|
||||
```rush
|
||||
if $IS_ROOT {
|
||||
echo "Running with root privileges"
|
||||
} else {
|
||||
echo "Running as normal user"
|
||||
}
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Permission validation
|
||||
- Security checks
|
||||
- Conditional behavior based on privileges
|
||||
|
||||
```rush
|
||||
# Require root for system operations
|
||||
if not $IS_ROOT {
|
||||
echo "ERROR: This script must be run as root"
|
||||
echo "Please run with: sudo rush script.rsh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Proceeding with system modifications..."
|
||||
```
|
||||
|
||||
```rush
|
||||
# Warn but don't fail
|
||||
if not $IS_ROOT {
|
||||
echo "WARNING: Not running as root"
|
||||
echo "Some operations may fail"
|
||||
}
|
||||
|
||||
echo "Continuing anyway..."
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### User-Specific Paths
|
||||
|
||||
```rush
|
||||
PROJECT = "myapp"
|
||||
CONFIG_FILE = "$HOME/.config/$PROJECT/settings.conf"
|
||||
LOG_FILE = "$HOME/.local/share/$PROJECT/app.log"
|
||||
|
||||
echo "Config: $CONFIG_FILE"
|
||||
echo "Logs: $LOG_FILE"
|
||||
```
|
||||
|
||||
### Permission Validation
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
# Validate we have the right permissions
|
||||
if not $IS_ROOT {
|
||||
echo "This script requires root privileges"
|
||||
echo "Current user: $USER"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Running as root - proceeding with installation"
|
||||
```
|
||||
|
||||
### Environment Information
|
||||
|
||||
```rush
|
||||
echo "=== Environment Information ==="
|
||||
echo "User: $USER"
|
||||
echo "Home: $HOME"
|
||||
|
||||
if $IS_ROOT {
|
||||
echo "Privileges: root"
|
||||
} else {
|
||||
echo "Privileges: normal user"
|
||||
}
|
||||
```
|
||||
|
||||
### Conditional Behavior
|
||||
|
||||
```rush
|
||||
# Different behavior for root vs normal user
|
||||
if $IS_ROOT {
|
||||
INSTALL_DIR = "/opt/myapp"
|
||||
CONFIG_DIR = "/etc/myapp"
|
||||
} else {
|
||||
INSTALL_DIR = "$HOME/.local/share/myapp"
|
||||
CONFIG_DIR = "$HOME/.config/myapp"
|
||||
}
|
||||
|
||||
echo "Installing to: $INSTALL_DIR"
|
||||
echo "Config at: $CONFIG_DIR"
|
||||
```
|
||||
|
||||
## Built-in Commands
|
||||
|
||||
In addition to variables, Rush provides built-in commands:
|
||||
|
||||
### `echo`
|
||||
|
||||
Print output to stdout.
|
||||
|
||||
```rush
|
||||
echo "Hello, World!"
|
||||
echo "Multiple arguments" "are joined" "with spaces"
|
||||
|
||||
NAME = "Alice"
|
||||
echo "Hello, $NAME!"
|
||||
```
|
||||
|
||||
### `exit`
|
||||
|
||||
Exit the script with a status code.
|
||||
|
||||
```rush
|
||||
# Exit with success
|
||||
exit 0
|
||||
|
||||
# Exit with error
|
||||
exit 1
|
||||
|
||||
# Exit with custom code
|
||||
CODE = "42"
|
||||
exit $CODE
|
||||
```
|
||||
|
||||
**Common pattern:**
|
||||
```rush
|
||||
if not $REQUIRED_VAR {
|
||||
echo "ERROR: REQUIRED_VAR must be set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Continuing..."
|
||||
```
|
||||
|
||||
### `require_root`
|
||||
|
||||
Built-in helper that ensures the script is running as root, exiting if not.
|
||||
|
||||
```rush
|
||||
# This will exit if not root
|
||||
require_root
|
||||
|
||||
echo "This only runs as root"
|
||||
```
|
||||
|
||||
Equivalent to:
|
||||
```rush
|
||||
if not $IS_ROOT {
|
||||
echo "This script must be run as root"
|
||||
exit 1
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Currently, Rush built-in variables are limited to `$USER`, `$HOME`, and `$IS_ROOT`.
|
||||
|
||||
**Not currently supported:**
|
||||
- ❌ `$PATH` or other environment variables
|
||||
- ❌ `$PWD` (current working directory)
|
||||
- ❌ `$SHELL` (user's shell)
|
||||
- ❌ Custom environment variable access (like `$MY_VAR` from the environment)
|
||||
|
||||
### Workaround
|
||||
|
||||
For now, if you need other environment variables, you would need to run external commands to get them (if supported).
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always check built-ins exist** - Validate `$USER` and `$HOME` are set
|
||||
2. **Validate permissions early** - Check `$IS_ROOT` at script start
|
||||
3. **Provide clear error messages** - Tell users what went wrong
|
||||
4. **Document requirements** - Make permission requirements clear in comments
|
||||
5. **Use meaningful exit codes** - Exit with non-zero on errors
|
||||
|
||||
### Example Script Template
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
# Script: system-setup.rsh
|
||||
# Description: Configure system settings
|
||||
# Requirements: Must run as root
|
||||
|
||||
# Validate environment
|
||||
if not $USER {
|
||||
echo "ERROR: USER not set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if not $HOME {
|
||||
echo "ERROR: HOME not set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check permissions
|
||||
if not $IS_ROOT {
|
||||
echo "ERROR: This script must be run as root"
|
||||
echo "Current user: $USER"
|
||||
echo "Please run: sudo rush system-setup.rsh"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Main script logic
|
||||
echo "Configuring system as $USER (root)"
|
||||
# ... rest of script ...
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential additions:
|
||||
|
||||
- Access to all environment variables
|
||||
- `$PWD` for current directory
|
||||
- `$HOSTNAME` for system name
|
||||
- `$SHELL` for user's shell
|
||||
- Function to read environment: `env("VAR_NAME")`
|
||||
- Process ID: `$PID`
|
||||
- Parent process ID: `$PPID`
|
||||
|
||||
These are not currently implemented.
|
||||
214
docs/src/language/control-flow.md
Normal file
214
docs/src/language/control-flow.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Control Flow
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
Rush provides conditional execution through `if`/`else` statements.
|
||||
|
||||
## Basic If Statements
|
||||
|
||||
The simplest form checks if a variable is defined and non-empty:
|
||||
|
||||
```rush
|
||||
USER_NAME = "Alice"
|
||||
|
||||
if $USER_NAME {
|
||||
echo "Hello, $USER_NAME!"
|
||||
}
|
||||
# Output: Hello, Alice!
|
||||
```
|
||||
|
||||
## If-Else
|
||||
|
||||
Add an `else` branch for alternative execution:
|
||||
|
||||
```rush
|
||||
ENV = "production"
|
||||
|
||||
if $ENV {
|
||||
echo "Environment: $ENV"
|
||||
} else {
|
||||
echo "No environment set"
|
||||
}
|
||||
```
|
||||
|
||||
## Negation with `not`
|
||||
|
||||
Use `not` to check if a variable is empty or undefined:
|
||||
|
||||
```rush
|
||||
if not $IS_ROOT {
|
||||
echo "Not running as root"
|
||||
} else {
|
||||
echo "Running as root"
|
||||
}
|
||||
```
|
||||
|
||||
## Condition Evaluation
|
||||
|
||||
In Rush, conditions are evaluated as follows:
|
||||
|
||||
- **Truthy:** Variable exists and has a non-empty value
|
||||
- **Falsy:** Variable is empty or undefined
|
||||
|
||||
```rush
|
||||
EMPTY = ""
|
||||
FILLED = "data"
|
||||
|
||||
if $FILLED {
|
||||
echo "This runs" # ✅ Runs
|
||||
}
|
||||
|
||||
if $EMPTY {
|
||||
echo "This doesn't run" # ❌ Skipped
|
||||
}
|
||||
|
||||
if not $EMPTY {
|
||||
echo "Empty variable detected" # ✅ Runs
|
||||
}
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Permission Checks
|
||||
|
||||
```rush
|
||||
if not $IS_ROOT {
|
||||
echo "Warning: This script should be run as root"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Proceeding with root privileges..."
|
||||
```
|
||||
|
||||
### Environment Validation
|
||||
|
||||
```rush
|
||||
REQUIRED_VAR = "" # Simulating an undefined/empty variable
|
||||
|
||||
if not $REQUIRED_VAR {
|
||||
echo "ERROR: REQUIRED_VAR must be set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Configuration valid"
|
||||
```
|
||||
|
||||
### Feature Flags
|
||||
|
||||
```rush
|
||||
DEBUG_MODE = "true"
|
||||
|
||||
if $DEBUG_MODE {
|
||||
echo "Debug mode enabled"
|
||||
echo "Verbose logging active"
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Step Validation
|
||||
|
||||
```rush
|
||||
CONFIG_FILE = "/etc/myapp/config.conf"
|
||||
DATA_DIR = "/var/lib/myapp"
|
||||
|
||||
if $CONFIG_FILE {
|
||||
echo "Config: $CONFIG_FILE"
|
||||
|
||||
if $DATA_DIR {
|
||||
echo "Data directory: $DATA_DIR"
|
||||
echo "All paths configured"
|
||||
} else {
|
||||
echo "ERROR: Data directory not set"
|
||||
}
|
||||
} else {
|
||||
echo "ERROR: Config file not set"
|
||||
}
|
||||
```
|
||||
|
||||
## Nested Conditions
|
||||
|
||||
You can nest `if` statements:
|
||||
|
||||
```rush
|
||||
ENV = "production"
|
||||
BACKUP_ENABLED = "yes"
|
||||
|
||||
if $ENV {
|
||||
echo "Environment: $ENV"
|
||||
|
||||
if $BACKUP_ENABLED {
|
||||
echo "Backups are enabled"
|
||||
} else {
|
||||
echo "Warning: Backups disabled"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
Current limitations of Rush conditionals:
|
||||
|
||||
- ❌ No `elif` or `else if` (use nested `if` instead)
|
||||
- ❌ No comparison operators (`==`, `!=`, `<`, `>`)
|
||||
- ❌ No logical operators (`&&`, `||`) beyond `not`
|
||||
- ❌ No string matching or regex
|
||||
- ❌ No numeric comparisons
|
||||
- ❌ Can only test variable truthiness
|
||||
|
||||
### Workaround Example
|
||||
|
||||
Since there's no `elif`, use nested conditions:
|
||||
|
||||
```rush
|
||||
MODE = "production"
|
||||
|
||||
if $MODE {
|
||||
# Check what MODE actually is would require comparison operators
|
||||
# For now, any non-empty value is truthy
|
||||
echo "Mode is set to: $MODE"
|
||||
} else {
|
||||
echo "Mode not set, using default"
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Keep conditions simple** - Rush conditionals are basic, so keep logic straightforward
|
||||
2. **Use descriptive variable names** - Make intent clear since you can't use complex expressions
|
||||
3. **Validate early** - Check required conditions at the start of your script
|
||||
4. **Provide clear messages** - Echo helpful information in each branch
|
||||
5. **Use exit codes** - Exit with non-zero status on errors
|
||||
|
||||
### Example: Script Validation
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
# Validate environment
|
||||
if not $USER {
|
||||
echo "ERROR: USER not set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if not $HOME {
|
||||
echo "ERROR: HOME not set"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Proceed with script
|
||||
echo "Environment validated for $USER"
|
||||
echo "Home directory: $HOME"
|
||||
|
||||
# Execute main logic here...
|
||||
```
|
||||
|
||||
## Future Improvements
|
||||
|
||||
Potential future enhancements to control flow:
|
||||
|
||||
- `elif` for multi-way branching
|
||||
- Comparison operators for string/numeric comparison
|
||||
- Logical operators for combining conditions
|
||||
- Pattern matching
|
||||
- Case/switch statements
|
||||
|
||||
These are not currently implemented.
|
||||
264
docs/src/language/loops.md
Normal file
264
docs/src/language/loops.md
Normal file
@@ -0,0 +1,264 @@
|
||||
# Loops
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
Rush supports iteration through `for` loops.
|
||||
|
||||
## Basic For Loop
|
||||
|
||||
Loop over a space-separated list of items:
|
||||
|
||||
```rush
|
||||
for name in Alice Bob Charlie {
|
||||
echo "Hello, $name!"
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
Hello, Alice!
|
||||
Hello, Bob!
|
||||
Hello, Charlie!
|
||||
```
|
||||
|
||||
## Loop Variable
|
||||
|
||||
The loop variable takes on each value in sequence:
|
||||
|
||||
```rush
|
||||
for number in 1 2 3 4 5 {
|
||||
echo "Number: $number"
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
Number: 1
|
||||
Number: 2
|
||||
Number: 3
|
||||
Number: 4
|
||||
Number: 5
|
||||
```
|
||||
|
||||
## Iterating Over Configuration
|
||||
|
||||
Common pattern for processing multiple items:
|
||||
|
||||
```rush
|
||||
SERVERS = "web-1 web-2 web-3"
|
||||
|
||||
for server in web-1 web-2 web-3 {
|
||||
echo "Deploying to $server"
|
||||
# Deployment commands here
|
||||
}
|
||||
```
|
||||
|
||||
## Using Variables in Loops
|
||||
|
||||
You can use variables within the loop body:
|
||||
|
||||
```rush
|
||||
ENV = "production"
|
||||
BASE_URL = "https://api.example.com"
|
||||
|
||||
for endpoint in users posts comments {
|
||||
URL = "$BASE_URL/$endpoint"
|
||||
echo "Checking $URL in $ENV"
|
||||
}
|
||||
```
|
||||
|
||||
## Nested Loops
|
||||
|
||||
Loops can be nested for multi-dimensional iteration:
|
||||
|
||||
```rush
|
||||
for env in dev staging prod {
|
||||
echo "Environment: $env"
|
||||
|
||||
for server in web-1 web-2 {
|
||||
HOSTNAME = "$server.$env.example.com"
|
||||
echo " - $HOSTNAME"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
Environment: dev
|
||||
- web-1.dev.example.com
|
||||
- web-2.dev.example.com
|
||||
Environment: staging
|
||||
- web-1.staging.example.com
|
||||
- web-2.staging.example.com
|
||||
Environment: prod
|
||||
- web-1.prod.example.com
|
||||
- web-2.prod.example.com
|
||||
```
|
||||
|
||||
## Conditionals in Loops
|
||||
|
||||
Combine loops with `if` statements:
|
||||
|
||||
```rush
|
||||
for item in file1 file2 file3 {
|
||||
if $item {
|
||||
echo "Processing $item"
|
||||
# Process the file
|
||||
} else {
|
||||
echo "Skipping empty item"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Processing Files
|
||||
|
||||
```rush
|
||||
for file in config.yml database.yml secrets.yml {
|
||||
FILE_PATH = "/etc/app/$file"
|
||||
echo "Loading $FILE_PATH"
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Stage Pipeline
|
||||
|
||||
```rush
|
||||
echo "Build Pipeline"
|
||||
|
||||
for stage in fetch compile test package deploy {
|
||||
echo "[$stage] Starting..."
|
||||
# Stage-specific logic here
|
||||
echo "[$stage] Complete"
|
||||
}
|
||||
```
|
||||
|
||||
### Server Configuration
|
||||
|
||||
```rush
|
||||
APP = "myapp"
|
||||
|
||||
for region in us-east us-west eu-west {
|
||||
SERVER = "$APP-$region"
|
||||
echo "Configuring $SERVER"
|
||||
}
|
||||
```
|
||||
|
||||
### Cleanup Tasks
|
||||
|
||||
```rush
|
||||
TEMP_DIR = "/tmp/build"
|
||||
|
||||
for artifact in logs cache temp build {
|
||||
ARTIFACT_PATH = "$TEMP_DIR/$artifact"
|
||||
echo "Removing $ARTIFACT_PATH"
|
||||
}
|
||||
```
|
||||
|
||||
## Loop Variable Scope
|
||||
|
||||
Loop variables persist after the loop ends with their last value:
|
||||
|
||||
```rush
|
||||
for item in a b c {
|
||||
echo "Current: $item"
|
||||
}
|
||||
|
||||
echo "Last item was: $item"
|
||||
# Output: Last item was: c
|
||||
```
|
||||
|
||||
This may change in future versions to limit scope to the loop body.
|
||||
|
||||
## Limitations
|
||||
|
||||
Current limitations of Rush loops:
|
||||
|
||||
- ❌ Only `for` loops (no `while` or `until`)
|
||||
- ❌ No `break` or `continue` statements
|
||||
- ❌ No range syntax (like `1..10`)
|
||||
- ❌ Cannot iterate over arrays (Rush has no arrays)
|
||||
- ❌ Cannot iterate over command output (like `for i in $(ls)`)
|
||||
- ❌ No C-style `for(i=0; i<10; i++)` syntax
|
||||
- ❌ Loop items must be explicitly listed
|
||||
|
||||
### Workarounds
|
||||
|
||||
Since you can't iterate over command output, you need to explicitly list items:
|
||||
|
||||
```rush
|
||||
# ❌ Not supported (yet):
|
||||
# for file in $(ls *.txt) { ... }
|
||||
|
||||
# ✅ Instead, list explicitly:
|
||||
for file in file1.txt file2.txt file3.txt {
|
||||
echo "Processing $file"
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use descriptive loop variables** - `for server in ...` is clearer than `for i in ...`
|
||||
2. **Keep loop bodies simple** - Complex logic should be broken down
|
||||
3. **Document what you're iterating** - Add comments for clarity
|
||||
4. **Consider parallel execution** - If iterations are independent, use `parallel` blocks
|
||||
|
||||
### Good Example
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
# Deploy to multiple environments
|
||||
echo "Starting deployment"
|
||||
|
||||
for env in dev staging production {
|
||||
echo ""
|
||||
echo "=== Deploying to $env ==="
|
||||
|
||||
DEPLOY_URL = "https://deploy.$env.example.com"
|
||||
echo "Target: $DEPLOY_URL"
|
||||
|
||||
# Deployment steps
|
||||
for step in backup deploy verify {
|
||||
echo " [$step] Running..."
|
||||
}
|
||||
|
||||
echo "=== $env deployment complete ==="
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo "All deployments finished"
|
||||
```
|
||||
|
||||
## Combining with Parallel Execution
|
||||
|
||||
For independent iterations, consider using parallel blocks instead:
|
||||
|
||||
```rush
|
||||
# Sequential (slow)
|
||||
for server in web-1 web-2 web-3 {
|
||||
echo "Deploying to $server"
|
||||
}
|
||||
|
||||
# Parallel (fast)
|
||||
parallel {
|
||||
run { echo "Deploying to web-1" }
|
||||
run { echo "Deploying to web-2" }
|
||||
run { echo "Deploying to web-3" }
|
||||
}
|
||||
```
|
||||
|
||||
See [Parallel Execution](./parallel.md) for more details.
|
||||
|
||||
## Future Improvements
|
||||
|
||||
Potential enhancements:
|
||||
|
||||
- `while` and `until` loops
|
||||
- `break` and `continue` statements
|
||||
- Range syntax: `for i in 1..10`
|
||||
- Iterating over command output
|
||||
- Array iteration
|
||||
- Step values: `for i in 1..10 step 2`
|
||||
|
||||
These are not currently implemented.
|
||||
331
docs/src/language/parallel.md
Normal file
331
docs/src/language/parallel.md
Normal file
@@ -0,0 +1,331 @@
|
||||
# Parallel Execution
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
One of Rush's key features is built-in support for parallel execution through `parallel` blocks.
|
||||
|
||||
## Basic Parallel Block
|
||||
|
||||
Run multiple tasks concurrently:
|
||||
|
||||
```rush
|
||||
parallel {
|
||||
run {
|
||||
echo "Task 1"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Task 2"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Task 3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The tasks run simultaneously, so output may be interleaved:
|
||||
```
|
||||
Task 1
|
||||
Task 3
|
||||
Task 2
|
||||
```
|
||||
|
||||
## When to Use Parallel Execution
|
||||
|
||||
Use parallel blocks when:
|
||||
|
||||
- ✅ Tasks are **independent** (don't depend on each other)
|
||||
- ✅ Tasks are **I/O bound** (network, disk operations)
|
||||
- ✅ You want to **save time** by running concurrently
|
||||
- ✅ Order of completion doesn't matter
|
||||
|
||||
Don't use parallel blocks when:
|
||||
|
||||
- ❌ Tasks must run in **specific order**
|
||||
- ❌ Tasks **share state** or modify the same resources
|
||||
- ❌ Tasks are **CPU intensive** and would compete for resources
|
||||
- ❌ You need **deterministic output** order
|
||||
|
||||
## Practical Examples
|
||||
|
||||
### Deploying to Multiple Servers
|
||||
|
||||
```rush
|
||||
APP = "my-service"
|
||||
VERSION = "1.2.3"
|
||||
|
||||
echo "Deploying $APP v$VERSION to all servers..."
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo "[web-1] Starting deployment"
|
||||
echo "[web-1] Deployment complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[web-2] Starting deployment"
|
||||
echo "[web-2] Deployment complete"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[web-3] Starting deployment"
|
||||
echo "[web-3] Deployment complete"
|
||||
}
|
||||
}
|
||||
|
||||
echo "All servers updated!"
|
||||
```
|
||||
|
||||
### Running Multiple Tests
|
||||
|
||||
```rush
|
||||
echo "Running test suite in parallel..."
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo "[unit-tests] Running..."
|
||||
echo "[unit-tests] 127 tests passed"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[integration-tests] Running..."
|
||||
echo "[integration-tests] 45 tests passed"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[lint] Running..."
|
||||
echo "[lint] No issues found"
|
||||
}
|
||||
}
|
||||
|
||||
echo "All tests complete!"
|
||||
```
|
||||
|
||||
### Data Processing Batches
|
||||
|
||||
```rush
|
||||
DATA_DIR = "$HOME/data"
|
||||
|
||||
echo "Processing data batches..."
|
||||
|
||||
parallel {
|
||||
run {
|
||||
INPUT = "$DATA_DIR/batch_001.csv"
|
||||
echo "[batch-001] Processing $INPUT"
|
||||
echo "[batch-001] Complete"
|
||||
}
|
||||
|
||||
run {
|
||||
INPUT = "$DATA_DIR/batch_002.csv"
|
||||
echo "[batch-002] Processing $INPUT"
|
||||
echo "[batch-002] Complete"
|
||||
}
|
||||
|
||||
run {
|
||||
INPUT = "$DATA_DIR/batch_003.csv"
|
||||
echo "[batch-003] Processing $INPUT"
|
||||
echo "[batch-003] Complete"
|
||||
}
|
||||
}
|
||||
|
||||
echo "All batches processed!"
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
|
||||
```rush
|
||||
echo "Checking service health..."
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo "[database] Checking connection..."
|
||||
echo "[database] OK"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[cache] Checking Redis..."
|
||||
echo "[cache] OK"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[api] Checking endpoint..."
|
||||
echo "[api] OK"
|
||||
}
|
||||
}
|
||||
|
||||
echo "All services healthy"
|
||||
```
|
||||
|
||||
## Variable Access
|
||||
|
||||
Variables defined before the `parallel` block are accessible inside:
|
||||
|
||||
```rush
|
||||
PROJECT = "my-app"
|
||||
ENV = "production"
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo "Deploying $PROJECT to server-1 ($ENV)"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "Deploying $PROJECT to server-2 ($ENV)"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
Current limitations of parallel execution in Rush:
|
||||
|
||||
- ❌ **Cannot define variables** inside `run` blocks
|
||||
- ❌ **No synchronization** primitives (no locks, semaphores)
|
||||
- ❌ **No return values** from parallel blocks
|
||||
- ❌ **No error propagation** (if one task fails, others continue)
|
||||
- ❌ **Fixed worker thread count** (currently hardcoded to 4)
|
||||
- ❌ **No task dependencies** (can't say "run A, then B and C in parallel")
|
||||
- ❌ **Output interleaving** (output from tasks mixed randomly)
|
||||
|
||||
### Variable Limitation Example
|
||||
|
||||
```rush
|
||||
# ❌ This doesn't work:
|
||||
parallel {
|
||||
run {
|
||||
MY_VAR = "value" # ERROR: Can't define variables in run blocks
|
||||
echo $MY_VAR
|
||||
}
|
||||
}
|
||||
|
||||
# ✅ Define variables before the parallel block:
|
||||
MY_VAR = "value"
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo $MY_VAR # OK: Can read existing variables
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Thread Pool
|
||||
|
||||
Rush currently uses a fixed pool of 4 worker threads. This means:
|
||||
|
||||
- If you have 4 tasks, they all run simultaneously
|
||||
- If you have 10 tasks, 4 run at a time, then the next 4, then the final 2
|
||||
|
||||
```rush
|
||||
# All run simultaneously (4 tasks, 4 threads)
|
||||
parallel {
|
||||
run { echo "A" }
|
||||
run { echo "B" }
|
||||
run { echo "C" }
|
||||
run { echo "D" }
|
||||
}
|
||||
|
||||
# Runs in batches (8 tasks, 4 threads)
|
||||
parallel {
|
||||
run { echo "1" } # First batch
|
||||
run { echo "2" } # First batch
|
||||
run { echo "3" } # First batch
|
||||
run { echo "4" } # First batch
|
||||
run { echo "5" } # Second batch (waits)
|
||||
run { echo "6" } # Second batch (waits)
|
||||
run { echo "7" } # Second batch (waits)
|
||||
run { echo "8" } # Second batch (waits)
|
||||
}
|
||||
```
|
||||
|
||||
### I/O vs CPU Bound
|
||||
|
||||
Parallel execution works best for I/O-bound tasks:
|
||||
|
||||
```rush
|
||||
# ✅ Good use case (I/O bound)
|
||||
parallel {
|
||||
run { echo "Downloading file 1..." }
|
||||
run { echo "Downloading file 2..." }
|
||||
run { echo "Downloading file 3..." }
|
||||
}
|
||||
|
||||
# ⚠️ May not help much (CPU bound)
|
||||
parallel {
|
||||
run { echo "Computing hash 1..." }
|
||||
run { echo "Computing hash 2..." }
|
||||
run { echo "Computing hash 3..." }
|
||||
}
|
||||
```
|
||||
|
||||
## Combining Parallel with Loops
|
||||
|
||||
You can't directly parallelize a loop, but you can manually write parallel tasks:
|
||||
|
||||
```rush
|
||||
# ❌ Can't do this (loop over parallel tasks):
|
||||
# for server in web-1 web-2 web-3 {
|
||||
# run { echo "Deploy to $server" }
|
||||
# }
|
||||
|
||||
# ✅ Instead, write out each task:
|
||||
parallel {
|
||||
run { echo "Deploy to web-1" }
|
||||
run { echo "Deploy to web-2" }
|
||||
run { echo "Deploy to web-3" }
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Keep run blocks simple** - Complex logic is harder to debug when parallel
|
||||
2. **Prefix output** - Use `[task-name]` prefixes to identify which task is logging
|
||||
3. **Make tasks independent** - Don't rely on order of execution
|
||||
4. **Use for I/O operations** - Network requests, file operations, database queries
|
||||
5. **Avoid shared state** - Don't modify the same resources from multiple tasks
|
||||
|
||||
### Good Example
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
BUILD_ID = "12345"
|
||||
REGISTRY = "registry.example.com"
|
||||
|
||||
echo "Starting parallel build verification"
|
||||
|
||||
parallel {
|
||||
run {
|
||||
echo "[checksums] Computing artifact checksums..."
|
||||
echo "[checksums] SHA256: abc123def456"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[docker] Verifying container image..."
|
||||
echo "[docker] Image $REGISTRY/app:$BUILD_ID verified"
|
||||
}
|
||||
|
||||
run {
|
||||
echo "[tests] Running smoke tests..."
|
||||
echo "[tests] All smoke tests passed"
|
||||
}
|
||||
}
|
||||
|
||||
echo "Verification complete for build $BUILD_ID"
|
||||
```
|
||||
|
||||
## Future Improvements
|
||||
|
||||
Potential enhancements:
|
||||
|
||||
- Configurable worker thread count
|
||||
- Error handling and propagation
|
||||
- Waiting for specific tasks
|
||||
- Task dependencies (DAG execution)
|
||||
- Return values from parallel tasks
|
||||
- Synchronized output (prevent interleaving)
|
||||
- Progress indicators
|
||||
|
||||
These are not currently implemented.
|
||||
188
docs/src/language/variables.md
Normal file
188
docs/src/language/variables.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Variables
|
||||
|
||||
> ⚠️ This documentation is AI-generated and may contain errors.
|
||||
|
||||
Variables in Rush are simple to use and automatically interpolated in strings.
|
||||
|
||||
## Declaration and Assignment
|
||||
|
||||
Variables are declared and assigned using the `=` operator:
|
||||
|
||||
```rush
|
||||
NAME = "Alice"
|
||||
AGE = "30"
|
||||
CITY = "San Francisco"
|
||||
```
|
||||
|
||||
**Note:** Currently, all values are treated as strings in Rush.
|
||||
|
||||
## Variable Naming Rules
|
||||
|
||||
Variable names:
|
||||
- Must start with a letter or underscore
|
||||
- Can contain letters, numbers, and underscores
|
||||
- Are case-sensitive
|
||||
- Should be in UPPER_CASE by convention (though not required)
|
||||
|
||||
```rush
|
||||
valid_name = "yes"
|
||||
ALSO_VALID = "yes"
|
||||
name123 = "yes"
|
||||
_private = "yes"
|
||||
|
||||
# Invalid (will cause parse errors):
|
||||
# 123invalid = "no" # Can't start with number
|
||||
# my-var = "no" # Hyphens not allowed
|
||||
```
|
||||
|
||||
## String Interpolation
|
||||
|
||||
Variables are automatically interpolated when prefixed with `$`:
|
||||
|
||||
```rush
|
||||
USER_NAME = "Alice"
|
||||
GREETING = "Hello, $USER_NAME!"
|
||||
echo $GREETING
|
||||
# Output: Hello, Alice!
|
||||
```
|
||||
|
||||
### Nested Interpolation
|
||||
|
||||
Variables can reference other variables:
|
||||
|
||||
```rush
|
||||
PROJECT = "my-app"
|
||||
VERSION = "2.1.0"
|
||||
ARTIFACT = "$PROJECT-$VERSION.tar.gz"
|
||||
|
||||
echo $ARTIFACT
|
||||
# Output: my-app-2.1.0.tar.gz
|
||||
```
|
||||
|
||||
### Path Construction
|
||||
|
||||
Common pattern for building paths:
|
||||
|
||||
```rush
|
||||
BASE_DIR = "$HOME/projects"
|
||||
PROJECT_NAME = "rush"
|
||||
PROJECT_DIR = "$BASE_DIR/$PROJECT_NAME"
|
||||
|
||||
echo $PROJECT_DIR
|
||||
# Output: /home/user/projects/rush
|
||||
```
|
||||
|
||||
## Validation and Errors
|
||||
|
||||
Rush validates variable usage at parse time:
|
||||
|
||||
```rush
|
||||
# ❌ ERROR: Variable used before definition
|
||||
echo $UNDEFINED_VAR
|
||||
MESSAGE = "Hello"
|
||||
|
||||
# ✅ CORRECT: Define before use
|
||||
MESSAGE = "Hello"
|
||||
echo $MESSAGE
|
||||
```
|
||||
|
||||
This strict validation helps catch typos and undefined variable references early.
|
||||
|
||||
## Variable Scope
|
||||
|
||||
### Global Scope
|
||||
|
||||
Variables defined at the top level are available throughout the script:
|
||||
|
||||
```rush
|
||||
GLOBAL_VAR = "accessible everywhere"
|
||||
|
||||
if $GLOBAL_VAR {
|
||||
echo $GLOBAL_VAR # ✅ Works
|
||||
}
|
||||
|
||||
for item in a b c {
|
||||
echo $GLOBAL_VAR # ✅ Works
|
||||
}
|
||||
```
|
||||
|
||||
### Loop Variables
|
||||
|
||||
Loop variables are scoped to the loop body:
|
||||
|
||||
```rush
|
||||
for item in x y z {
|
||||
# 'item' is available here
|
||||
echo "Processing $item"
|
||||
}
|
||||
|
||||
# 'item' retains its last value after the loop
|
||||
echo "Last item was: $item"
|
||||
```
|
||||
|
||||
**Note:** Currently, Rush has simple scoping rules. Variables defined in loops persist after the loop exits with their last assigned value.
|
||||
|
||||
## Built-in Variables
|
||||
|
||||
Rush provides several built-in variables (see [Built-in Variables](./builtins.md) for details):
|
||||
|
||||
```rush
|
||||
echo "User: $USER"
|
||||
echo "Home: $HOME"
|
||||
|
||||
if $IS_ROOT {
|
||||
echo "Running as root"
|
||||
}
|
||||
```
|
||||
|
||||
## Escaping Variables
|
||||
|
||||
Currently, Rush does not support escaping `$` to print it literally. If you need a literal `$`, you may need to work around this limitation.
|
||||
|
||||
```rush
|
||||
# This will attempt variable interpolation:
|
||||
echo "Price: $100" # Looks for variable named "100"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Define variables at the top** of your script for clarity
|
||||
2. **Use descriptive names** that indicate purpose
|
||||
3. **Group related variables** together
|
||||
4. **Use UPPER_CASE** for constants/configuration
|
||||
5. **Validate inputs** early in your script
|
||||
|
||||
### Example
|
||||
|
||||
```rush
|
||||
#!/usr/bin/env rush
|
||||
|
||||
# Configuration
|
||||
APP_NAME = "my-service"
|
||||
APP_VERSION = "1.0.0"
|
||||
DEPLOY_ENV = "production"
|
||||
|
||||
# Paths
|
||||
BASE_DIR = "/opt/apps"
|
||||
APP_DIR = "$BASE_DIR/$APP_NAME"
|
||||
LOG_DIR = "/var/log/$APP_NAME"
|
||||
|
||||
# Deployment
|
||||
ARTIFACT = "$APP_NAME-$APP_VERSION.tar.gz"
|
||||
ARTIFACT_URL = "https://releases.example.com/$ARTIFACT"
|
||||
|
||||
echo "Deploying $ARTIFACT to $DEPLOY_ENV"
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
Current limitations of Rush variables:
|
||||
|
||||
- ❌ No arrays or lists
|
||||
- ❌ No numeric operations
|
||||
- ❌ No string manipulation functions
|
||||
- ❌ No variable expansion modifiers (like `${var:-default}`)
|
||||
- ❌ All values are strings
|
||||
- ❌ No explicit quoting mechanism
|
||||
|
||||
These limitations may be addressed in future versions of Rush.
|
||||
Reference in New Issue
Block a user