| Crates.io | rush-sh |
| lib.rs | rush-sh |
| version | 0.8.0 |
| created_at | 2025-09-12 05:39:44.159857+00 |
| updated_at | 2026-01-17 06:19:03.728714+00 |
| description | A POSIX sh-compatible shell written in Rust |
| homepage | |
| repository | https://github.com/drewwalton19216801/rush-sh |
| max_upload_size | |
| id | 1835218 |
| size | 3,404,616 |
Version 0.8.0 - A comprehensive POSIX sh-compatible shell implementation

Rush is a POSIX sh-compatible shell implemented in Rust (~96% POSIX compliant). It provides both interactive mode with a REPL prompt and script mode for executing commands from files. The shell supports comprehensive shell features including command execution, pipes, redirections, subshells, file descriptor operations, environment variables, and 32 built-in commands.
alias hurry='rush -c "do the thing"'βbecause sometimes you just need to rush to judgment.(command) syntax
| operator.<) and output (>, >>, >|) redirections, here-documents (<<), and here-strings (<<<).
>| to force overwrite files even when noclobber (set -C) is enabled2>errors.log, 3>output.txt3<input.txt, 4<data.txt2>>errors.log, 3>>output.txt2>&1 (stderr to stdout), 1>&2 (stdout to stderr), 3>&12>&- (close stderr), 3>&-3<>file.txt (open for both reading and writing)cmd >out.txt 2>err.txt 3>custom.txt{a,b,c} expands to a b c{1..5} expands to 1 2 3 4 5{a..e} expands to a b c d efile{1,2,3}.txt expands to file1.txt file2.txt file3.txt{{a,b},{c,d}} expands to a b c d$(command) syntax: echo "Current dir: $(pwd)"`command` syntax: echo "Files:ls | wc -l"echo $(echo $HOME)$((...)) syntax.
echo $((2 + 3 * 4))result=$((x * y + z))$((5 > 3)) returns 1 (true) or 0 (false)$((5 & 3)), $((x && y))VAR=value and VAR="quoted value"$VAR and ${VAR} (both syntaxes supported for all variable types)$?, $$, $0, $!, $LINENO (with full ${VAR} brace syntax support)sleep 10 & echo $!)${VAR:-default} - use default if VAR is unset or null${VAR:=default} - assign default if VAR is unset or null${VAR:+replacement} - use replacement if VAR is set and not null${VAR:?error} - display error if VAR is unset or null${VAR:offset} - substring starting at offset${VAR:offset:length} - substring with length${#VAR} - length of VAR${VAR#pattern} - remove shortest match from beginning${VAR##pattern} - remove longest match from beginning${VAR%pattern} - remove shortest match from end${VAR%%pattern} - remove longest match from end${VAR/pattern/replacement} - pattern substitution${VAR//pattern/replacement} - global pattern substitution${!name} - indirect expansion (bash extension)${!prefix*} and ${!prefix@} - variable name expansion (bash extension)export VAR and export VAR=value$1, $2, $3, etc. for accessing script arguments$* and $@ for accessing all arguments as a single string$# returns the number of positional parametersshift [n] builtin to shift positional parameters./rush-sh script.sh arg1 arg2 arg3if statements: if condition; then commands; elif condition; then commands; else commands; ficase statements with glob pattern matching: case word in pattern1|pattern2) commands ;; *.txt) commands ;; *) default ;; esacfor loops: for variable in item1 item2 item3; do commands; donewhile loops: while condition; do commands; doneuntil loops: until condition; do commands; donename() { commands; }name arg1 arg2local var=valuereturn [value]declare -f [function_name]{ commands; } syntax: (colon): Null command that always returns successalias: Define or display aliasesbg: Resume stopped jobs in the backgroundbreak: Exit from for, while, or until loops with optional [n] for nested loopscd: Change directorycontinue: Skip to next iteration of for, while, or until loops with optional [n] for nested loopsdeclare: Display function definitions and list function namesdirs: Display directory stackenv: List environment variablesexit: Exit the shellexport: Export variables to child processesfg: Bring background jobs to foregroundhelp: Show available commandsjobs: List background jobskill: Send signals to jobs or processespopd: Pop directory from stack and change to itpushd: Push directory onto stack and change to itpwd: Print working directoryreturn: Return from a function with an optional exit codeset: Set or unset shell options and positional parametersset_color_scheme: Switch between color themes (default/dark/light)set_colors: Enable/disable color output dynamicallyset_condensed: Enable/disable condensed cwd display in promptshift: Shift positional parameterssource / .: Execute a script file with rush (bypasses shebang and comment lines)test / [: POSIX-compatible test builtin with string and file teststimes: Display accumulated user and system CPU times for the shell and its child processestrap: Set or display signal handlerstype: Display information about command type (alias, keyword, function, builtin, or external command)unalias: Remove alias definitionsunset: Remove variableswait: Wait for background jobs to complete~/.rushrc on interactive shell startupsrc/, ../, /usr/bin/)~/ and ~/Documents/ pathscommand & runs commands in the backgroundjobs displays all background jobs with statusfg [jobspec] brings jobs to foregroundbg [jobspec] resumes stopped jobs in backgroundkill [signal] jobspec sends signals to jobswait [jobspec] waits for job completion%n, %, %-, %string, %?stringSubshell Support - Full POSIX-compliant subshell implementation with state isolation, exit code propagation, trap inheritance, and depth limit protection (max 100 levels). Includes 60+ comprehensive test cases covering all aspects of subshell behavior.
File Descriptor Operations - Complete FD table management with duplication (N>&M, N<&M), closing (N>&-, N<&-), and read/write (N<>) operations. Includes 30+ test cases for comprehensive coverage.
Complete Control Structures - Full implementation of POSIX control structures including for loops, while loops, until loops, and function definitions with local variable scoping, return statements, and recursion support.
Function System - Comprehensive function implementation with definition, calls, local variables (local keyword), return statements, recursion, and function introspection (declare -f).
Complete POSIX Parameter Expansion - Full implementation of ${VAR:-default}, ${VAR#pattern}, ${VAR/pattern/replacement}, and all other POSIX parameter expansion modifiers with comprehensive pattern matching and string manipulation capabilities.
Advanced Arithmetic Expansion - Complete $((...)) arithmetic expression evaluator with proper operator precedence, variable integration, bitwise operations, logical operations, and comprehensive error handling using the Shunting-yard algorithm.
Enhanced Built-in Command Suite - Comprehensive set of 26 built-in commands including the colon (:) null command, loop control (break/continue), directory stack management (pushd/popd/dirs), alias management (alias/unalias), color theming (set_colors/set_color_scheme), function introspection (declare), signal handling (trap), command type inspection (type), function returns (return), shell options (set), and POSIX-compliant test builtin.
Intelligent Tab Completion - Advanced completion system for commands, files, directories, and paths with support for nested directory traversal and home directory expansion.
Command Grouping - POSIX-compliant command grouping { commands; } for executing commands in the current shell context with shared state, variable persistence, and proper redirection handling.
Rush provides full POSIX-compliant subshell support, enabling command execution in isolated environments:
(command) syntaxBasic Usage:
# Execute command in subshell
(cd /tmp && ls)
pwd # Still in original directory
# Subshell with variable isolation
VAR=parent
(VAR=child; echo "In subshell: $VAR")
echo "In parent: $VAR" # Still shows "parent"
# Exit code propagation
(exit 42)
echo "Subshell exit code: $?" # Shows 42
# Trap inheritance
trap 'echo "Signal received"' INT
(sleep 10) # Ctrl+C will trigger inherited trap
Advanced Usage:
# Complex command isolation
(
cd /tmp
export TEMP_VAR=value
echo "Working in: $(pwd)"
)
# Original directory and environment preserved
# Pipeline with subshells
(echo "data" | grep "pattern") | wc -l
# Nested subshells (up to 100 levels)
(echo "Level 1"; (echo "Level 2"; (echo "Level 3")))
# Subshell with redirections
(echo "output" > file.txt; cat file.txt) 2>errors.log
Key Features:
Implementation Details:
For practical examples, see the example scripts that demonstrate subshell usage in various scenarios.
Rush implements POSIX-compliant command grouping, allowing multiple commands to be executed as a single unit in the current shell context:
{ command1; command2; } (must end with semicolon or newline before closing brace)Usage Examples:
# Grouping with redirection
{
echo "Date: $(date)"
echo "User: $USER"
} > session_info.txt
# Variable persistence (difference from subshells)
x=1
{ x=2; }
echo $x # Prints 2 (variables persist)
# Nested grouping
{
echo "Start"
{ echo "Middle"; }
echo "End"
}
Rush now provides comprehensive environment variable support with full POSIX compliance:
Variable Assignment: Support for both simple and quoted assignments
MY_VAR=hello
MY_VAR="hello world"
NAME="Alice"
Variable Expansion: Expand variables in commands with $VAR syntax
echo "Hello $NAME"
echo "Current directory: $PWD"
Special Variables: Built-in support for special shell variables
echo "Last exit code: $?"
echo "Shell PID: $$"
echo "Script name: $0"
Export Mechanism: Export variables to child processes
export MY_VAR
export NEW_VAR=value
Variable Management: Full lifecycle management with unset
unset MY_VAR
Multi-Mode Support: Variables work consistently across all execution modes
-c command stringsExample usage:
# Set and use variables
MY_VAR="Hello from Rush"
echo "Message: $MY_VAR"
# Export to child processes
export MY_VAR
env | grep MY_VAR
# Use in pipelines
echo "$MY_VAR" | grep "Rush"
# Special variables
if true; then echo "Success ($?)"; fi
Rush now supports comprehensive brace expansion, a powerful feature for generating multiple strings from patterns:
{a,b,c} generates multiple alternatives{1..10} generates sequences of numbers{a..z} generates sequences of lettersBasic Syntax:
# Comma-separated alternatives
echo {a,b,c}
# Output: a b c
echo file{1,2,3}.txt
# Output: file1.txt file2.txt file3.txt
# Numeric ranges
echo {1..5}
# Output: 1 2 3 4 5
echo test{1..3}.log
# Output: test1.log test2.log test3.log
# Alphabetic ranges
echo {a..e}
# Output: a b c d e
echo file{a..c}.txt
# Output: filea.txt fileb.txt filec.txt
Advanced Usage:
# Nested brace expansion
echo {{a,b},{c,d}}
# Output: a b c d
echo file{{1,2},{a,b}}.txt
# Output: file1.txt file2.txt filea.txt fileb.txt
# Multiple brace patterns in one command
echo {a,b}{1,2}
# Output: a1 a2 b1 b2
# With prefixes and suffixes
echo prefix_{a,b,c}_suffix
# Output: prefix_a_suffix prefix_b_suffix prefix_c_suffix
Real-World Examples:
# Create multiple directories
mkdir -p project/{src,test,docs}
# Create numbered backup files
cp important.txt important.txt.{1..5}
# Process multiple file types
cat file.{txt,md,log}
# Generate test data
echo user{1..100}@example.com
# Create directory structure
mkdir -p app/{controllers,models,views}/{admin,public}
# Batch file operations
mv photo{1..10}.jpg backup/
# Generate configuration files
touch config.{dev,staging,prod}.yml
Integration with Other Features:
# With pipes
echo {a,b,c} | tr ' ' '\n'
# With redirections
echo {1..5} > numbers.txt
# With variables
PREFIX="test"
echo ${PREFIX}{1..3}
# With command substitution
echo file{$(seq 1 5)}.txt
# In for loops
for file in document{1..5}.txt; do
touch "$file"
done
Key Features:
Implementation Details:
Rush now supports advanced case statements with full glob pattern matching capabilities:
* (any characters), ? (single character), and [abc] (character classes)| (e.g., *.txt|*.md)glob crateExample usage:
case $filename in
*.txt|*.md) echo "Text file" ;;
*.jpg|*.png) echo "Image file" ;;
file?) echo "Single character file" ;;
[abc]*) echo "Starts with a, b, or c" ;;
*) echo "Other file type" ;;
esac
Rush now supports directory stack management with the classic Unix pushd, popd, and dirs commands:
pushd <directory>: Changes to the specified directory and pushes the current directory onto the stackpopd: Pops the top directory from the stack and changes to itdirs: Displays the current directory stackExample usage:
# Start in home directory
pwd
# /home/user
# Push to /tmp and see stack
pushd /tmp
# /tmp /home/user
# Push to another directory
pushd /var
# /var /tmp /home/user
# See current stack
dirs
# /var /tmp /home/user
# Pop back to /tmp
popd
# /tmp /home/user
# Pop back to home
popd
# /home/user
This feature is particularly useful for:
Rush now supports comprehensive command substitution with both $(...) and `...` syntax, executing commands within the current shell context for optimal performance and functionality:
/bin/sh processes$(command) and `command` work identicallyArchitecture:
Command substitution in Rush is implemented through a sophisticated multi-stage architecture that ensures seamless integration with the shell's execution model:
$(...) and `...`) during tokenizationThe core execution engine implements a three-tier approach:
expand_variables_in_string)// Located in src/executor.rs:144-451
pub fn expand_variables_in_string(input: &str, shell_state: &mut ShellState) -> String
$() and ` patternsexecute_and_capture_output)// Located in src/executor.rs:10-130
fn execute_and_capture_output(ast: Ast, shell_state: &mut ShellState) -> Result<String, String>
ShellState as the parent shell/bin/sh spawning)This architecture enables command substitutions to behave identically to bash while leveraging Rust's type safety and performance characteristics, providing a seamless experience for shell scripting and interactive use.
Rush displays a condensed version of the current working directory in the interactive prompt by default, but this behavior is now fully configurable:
Configuration Options:
# Environment variable (set before starting shell)
export RUSH_CONDENSED=true # Enable condensed display (default)
export RUSH_CONDENSED=false # Enable full path display
# Runtime control (in already running shell)
set_condensed on # Enable condensed display
set_condensed off # Enable full path display
set_condensed status # Show current setting
Example Prompt Displays:
Condensed mode (default):
/h/d/p/r/rush $
/u/b/s/project $
/h/u/Documents $
Full path mode:
/home/drew/projects/rush-sh $
/usr/bin/src/project $
/home/user/Documents $
Usage Examples:
# Start with condensed display (default behavior)
rush-sh
# Start with full path display
RUSH_CONDENSED=false rush-sh
# Toggle in running shell
set_condensed off # Switch to full paths
set_condensed on # Switch back to condensed
set_condensed status # Check current setting
# In ~/.rushrc for permanent preference
echo 'export RUSH_CONDENSED=false' >> ~/.rushrc
This feature provides flexible control over prompt display while maintaining backward compatibility with the existing condensed format as the default.
Rush now supports comprehensive arithmetic expansion using the POSIX-standard $((...)) syntax, enabling mathematical computations directly in shell commands and scripts:
Basic Syntax:
# Simple arithmetic
echo "Result: $((2 + 3))"
echo "Multiplication: $((5 * 4))"
echo "Division: $((20 / 4))"
echo "Modulo: $((17 % 3))"
Variable Usage:
# Variables in arithmetic expressions
x=10
y=3
echo "x + y = $((x + y))"
echo "x * y = $((x * y))"
echo "x squared = $((x * x))"
Operator Precedence:
# Standard precedence: * / % before + -
echo "2 + 3 * 4 = $((2 + 3 * 4))" # 14 (not 20)
# Use parentheses to override precedence
echo "(2 + 3) * 4 = $(((2 + 3) * 4))" # 20
# Complex expressions
echo "2 * 3 + 4 * 5 = $((2 * 3 + 4 * 5))" # 26
Comparison Operations:
# Comparisons return 1 (true) or 0 (false)
if [ $((5 > 3)) -eq 1 ]; then echo "5 is greater than 3"; fi
if [ $((10 == 10)) -eq 1 ]; then echo "Equal"; fi
if [ $((7 != 5)) -eq 1 ]; then echo "Not equal"; fi
# Available comparison operators:
# == != < <= > >=
Bitwise and Logical Operations:
# Bitwise operations
echo "5 & 3 = $((5 & 3))" # 1 (binary AND)
echo "5 | 3 = $((5 | 3))" # 7 (binary OR)
echo "5 ^ 3 = $((5 ^ 3))" # 6 (binary XOR)
# Logical operations (non-zero = true)
echo "5 && 3 = $((5 && 3))" # 1 (both true)
echo "5 && 0 = $((5 && 0))" # 0 (second false)
echo "0 || 5 = $((0 || 5))" # 1 (second true)
Real-world Examples:
# Calculate area of rectangle
length=10
width=5
area=$((length * width))
echo "Area: $area"
# Temperature conversion
celsius=25
fahrenheit=$((celsius * 9 / 5 + 32))
echo "$celsiusΒ°C = ${fahrenheit}Β°F"
# Array length calculation (simulated)
items=8
per_page=3
pages=$(((items + per_page - 1) / per_page))
echo "Pages needed: $pages"
# Conditional logic with arithmetic
count=15
if [ $((count % 2)) -eq 0 ]; then
echo "Even number"
else
echo "Odd number"
fi
Error Handling:
# Division by zero produces an error
echo "Division by zero: $((5 / 0))"
# Undefined variables cause errors
echo "Undefined var: $((undefined_var + 1))"
Advanced Usage:
# Complex mathematical expressions
radius=5
pi=3
area=$((pi * radius * radius))
echo "Circle area: $area"
# Multiple operations in one expression
result=$(( (10 + 5) * 3 / 2 ))
echo "Complex result: $result"
# Use in variable assignments
x=10
y=$((x + 5)) # y = 15
z=$((y * 2)) # z = 30
Arithmetic expansion integrates seamlessly with all other shell features and works in interactive mode, scripts, and command strings.
# Basic command substitution
echo "Current directory: $(pwd)"
echo "Files in directory: `ls | wc -l`"
# Variable assignments with substitutions
PROJECT_DIR="$(pwd)/src"
FILE_COUNT="$(ls *.rs 2>/dev/null | wc -l)"
# Complex expressions
echo "Rust version: $(rustc --version | cut -d' ' -f2)"
echo "Files modified today: $(find . -name '*.rs' -mtime -1 | wc -l)"
# Error handling
NONEXISTENT="$(nonexistent_command 2>/dev/null || echo 'command failed')"
echo "Result: $NONEXISTENT"
# Multiple commands
echo "Combined output: $(echo 'Hello'; echo 'World')"
Command substitution works seamlessly with:
$(echo hello | grep ll) > output.txtecho $(echo $HOME)echo "Path: $(pwd)"$(find . -name "*.rs" -exec wc -l {} \;)Rush now provides comprehensive built-in alias support, allowing you to create shortcuts for frequently used commands:
alias name=value syntaxalias commandalias nameunalias nameExample usage:
# Create aliases
alias ll='ls -l'
alias la='ls -la'
alias ..='cd ..'
alias grep='grep --color=auto'
# List all aliases
alias
# Output:
# alias ll='ls -l'
# alias la='ls -la'
# alias ..='cd ..'
# alias grep='grep --color=auto'
# Show specific alias
alias ll
# Output: alias ll='ls -l'
# Use aliases (they expand automatically)
ll
la /tmp
..
# Remove aliases
unalias ll
alias # ll is no longer listed
# Error handling
unalias nonexistent # Shows: unalias: nonexistent: not found
Key Features:
Advanced Usage:
# Complex aliases with pipes and redirections
alias backup='cp -r ~/Documents ~/Documents.backup && echo "Backup completed"'
alias count='find . -name "*.rs" | wc -l'
# Aliases with variables (expanded at definition time)
MY_DIR="/tmp"
alias cleanup="rm -rf $MY_DIR/*"
# Function-like aliases
alias mkcd='mkdir -p "$1" && cd "$1"' # Note: $1 won't work as expected
Implementation Details:
Several features were fully implemented but not properly documented in previous versions:
For Loops - Complete implementation with for variable in items; do commands; done syntax, supporting variable assignment, multiple items, and integration with all shell features.
While Loops - Full implementation with while condition; do commands; done syntax, supporting complex conditions, nested loops, and proper exit code handling.
Until Loops - Full implementation with until condition; do commands; done syntax, executing commands until the condition becomes true (inverse of while loops), supporting complex conditions, nested loops, and proper exit code handling.
Function System - Comprehensive function implementation including:
name() { commands; }name arg1 arg2local var=valuereturn [value]declare -f [function_name]Arithmetic Implementation:
Rush now provides comprehensive support for the POSIX test builtin command and its [ bracket syntax, enabling powerful conditional logic in shell scripts:
-z) or non-empty (-n)-e), regular files (-f), and directories (-d)test and [ syntax work identicallyExample usage:
# String tests
if test -z ""; then echo "Empty string"; fi
if [ -n "hello" ]; then echo "Non-empty string"; fi
# File tests
if test -e "/tmp/file.txt"; then echo "File exists"; fi
if [ -d "/tmp" ]; then echo "Is directory"; fi
if test -f "/etc/passwd"; then echo "Is regular file"; fi
# Complex conditions
if [ -n "$MY_VAR" ] && test -e "$CONFIG_FILE"; then
echo "Variable set and config file exists"
fi
# Error handling
test -x "invalid_option" # Returns exit code 2
exit_code=$?
if [ $exit_code -eq 2 ]; then echo "Invalid option used"; fi
Key Features:
-z (zero length) and -n (non-zero length) tests-e (exists), -f (regular file), -d (directory)[ condition ] works identically to test conditionAdvanced Usage:
# Variable existence checks
MY_VAR="hello world"
if test -n "$MY_VAR"; then
echo "MY_VAR is set to: $MY_VAR"
fi
# Safe file operations
TARGET_FILE="/tmp/safe_file.txt"
if test -e "$TARGET_FILE"; then
echo "File exists, backing up..."
mv "$TARGET_FILE" "$TARGET_FILE.backup"
fi
# Directory creation with checks
TARGET_DIR="/tmp/test_dir"
if test -d "$TARGET_DIR"; then
echo "Directory already exists"
else
mkdir -p "$TARGET_DIR"
echo "Directory created"
fi
Rush now provides comprehensive signal handling through the POSIX-compliant trap builtin, enabling scripts to respond to signals and perform cleanup operations:
trap commandtrap - SIGNALtrap -l$? exit code per POSIX requirementsBasic Usage:
# Set trap for SIGINT (Ctrl+C)
trap 'echo "Interrupted! Cleaning up..."; exit 1' INT
# Set EXIT trap for cleanup
trap 'rm -rf /tmp/mytemp; echo "Cleanup complete"' EXIT
# Set trap for multiple signals
trap 'echo "Signal received"' INT TERM HUP
# Display all traps
trap
# Display specific trap
trap -p INT
# Reset trap to default
trap - INT
# Ignore signal
trap '' HUP
# List all signals
trap -l
Advanced Usage:
# Cleanup trap for temporary files
TEMP_DIR="/tmp/script_$$"
mkdir -p "$TEMP_DIR"
trap 'rm -rf "$TEMP_DIR"; echo "Temp files removed"' EXIT
# Signal handling in long operations
trap 'echo "Operation cancelled"; exit 130' INT TERM
for i in {1..100}; do
echo "Processing $i..."
sleep 1
done
# Variable expansion in traps
SCRIPT_START=$(date)
trap 'echo "Script started at: $SCRIPT_START"' EXIT
# Multiple commands in trap
trap 'echo "Cleaning up..."; rm -f *.tmp; echo "Done"' EXIT
Key Features:
Real-Time Execution:
As of v0.5.0, Rush Shell supports real-time signal trap execution during interactive sessions and script execution:
Implementation Details:
Arc<Mutex<HashMap>>)Integration with Shell Features:
# Trap with command substitution
trap 'echo "Files in directory: $(ls | wc -l)"' WINCH
# Trap with arithmetic expansion
COUNT=0
trap 'COUNT=$((COUNT + 1)); echo "Signal count: $COUNT"' USR1
# Trap with functions
cleanup() {
echo "Cleanup function called"
rm -rf /tmp/mytemp
}
trap cleanup EXIT
# Trap in scripts
#!/usr/bin/env rush-sh
trap 'echo "Script interrupted at line $LINENO"' INT
# ... rest of script
The trap builtin provides robust signal handling for production shell scripts while maintaining full backward compatibility with existing Rush shell functionality.
The test builtin is fully integrated with Rush's control structures, enabling complex conditional logic in scripts while maintaining POSIX compatibility.
Rush provides full support for here-documents (<<) and here-strings (<<<), enabling flexible multi-line and single-line input redirection:
Here-Document Syntax:
# Basic here-document
cat << EOF
This is line 1
This is line 2
This is line 3
EOF
# Here-document with variable expansion
NAME="Alice"
cat << EOF
Hello, $NAME!
Welcome to Rush shell.
Your home directory is: $HOME
EOF
# Here-document with quoted delimiter (no expansion)
cat << 'EOF'
Variables like $HOME are not expanded
They appear literally: $USER
EOF
# Here-document in a pipeline
cat << EOF | grep "important"
This line is important
This line is not
Another important line
EOF
# Here-document with command
grep "pattern" << EOF
line with pattern here
another line
pattern appears again
EOF
Here-String Syntax:
# Basic here-string
cat <<< "Hello, World!"
# Here-string with variable expansion
MESSAGE="Rush shell is awesome"
cat <<< "$MESSAGE"
# Here-string with grep
grep "rush" <<< "I love rush shell"
# Here-string in pipeline
cat <<< "test data" | tr 'a-z' 'A-Z'
# Here-string with multiple words
wc -w <<< "count these five words here"
# Here-string with special characters
cat <<< "Special chars: $HOME, $(date), `pwd`"
Advanced Usage:
# Here-document for multi-line variable assignment
read -r -d '' SCRIPT << 'EOF'
#!/usr/bin/env rush-sh
echo "This is a script"
echo "With multiple lines"
EOF
# Here-document with indentation (content preserves spacing)
cat << EOF
Indented line 1
More indented line 2
Back to first indent
EOF
# Here-string for quick testing
while read -r line; do
echo "Processing: $line"
done <<< "single line input"
# Here-document with arithmetic expansion
cat << EOF
Result: $((2 + 3))
Calculation: $((10 * 5))
EOF
# Here-string with command substitution
cat <<< "Current directory: $(pwd)"
# Multiple here-documents in sequence
cat << EOF1
First document
EOF1
cat << EOF2
Second document
EOF2
Real-World Examples:
# Generate configuration file
cat << EOF > config.yml
server:
host: localhost
port: 8080
database:
name: mydb
user: $DB_USER
EOF
# Create SQL script
mysql -u root << EOF
CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;
CREATE TABLE users (id INT, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob');
EOF
# Send email with here-document
mail -s "Subject" user@example.com << EOF
Dear User,
This is the email body.
It can span multiple lines.
Best regards,
Rush Shell
EOF
# Quick data processing with here-string
# Count words in a string
wc -w <<< "The quick brown fox jumps"
# Convert to uppercase
tr 'a-z' 'A-Z' <<< "convert this text"
# Search for pattern
grep -o "word" <<< "find word in this string"
# Process JSON with here-string
jq '.name' <<< '{"name": "Rush", "type": "shell"}'
Key Features:
Implementation Details:
Rush provides comprehensive POSIX-compliant file descriptor management, enabling advanced I/O redirection and control over file descriptors beyond the standard stdin (0), stdout (1), and stderr (2):
Basic FD Redirection:
# Redirect stderr to a file (FD 2)
ls /nonexistent 2>errors.log
# Redirect stdout to one file, stderr to another
command >output.log 2>errors.log
# Append stderr to a file
command 2>>errors.log
# Open file for reading on FD 3
cat 3<input.txt
# Open file for reading and writing on FD 3
cat 3<>file.txt
FD Duplication:
# Redirect stderr to stdout (combine streams)
command 2>&1
# Redirect stdout to stderr
echo "Error message" 1>&2
# Redirect FD 3 to stdout
command 3>&1
# Combine stderr into stdout, then pipe both
command 2>&1 | grep pattern
FD Closing:
# Close stderr to suppress error messages
command 2>&-
# Close FD 3
command 3>&-
# Discard all output
command >/dev/null 2>&1
Advanced Patterns:
# Separate stdout and stderr to different files
command >output.txt 2>errors.txt
# Combine streams and redirect to file
command >combined.log 2>&1
# Swap stdout and stderr
command 3>&1 1>&2 2>&3 3>&-
# Multiple custom file descriptors
command 3>custom1.txt 4>custom2.txt 5>custom3.txt
# Pipeline with error handling
command 2>&1 | tee output.log | grep ERROR
# Conditional error logging
if ! command 2>errors.log; then
cat errors.log
exit 1
fi
Practical Use Cases:
# Logging: Separate normal output from errors
./script.sh >output.log 2>errors.log
# Debugging: Capture stderr while displaying stdout
command 2>debug.log
# Silent execution: Discard all output
command >/dev/null 2>&1
# Error analysis: Capture and process errors
command 2>&1 | grep -i error | tee error_summary.txt
# Stream separation: Process stdout and stderr differently
(command | process_output) 2> >(process_errors)
# Backup with logging
tar czf backup.tar.gz /data 2>backup_errors.log
# Complex pipelines with error tracking
(command1 2>&1 | command2) 2>pipeline_errors.log
Key Features:
Implementation Details:
FileDescriptorTable in shell stateFor a complete demonstration of file descriptor operations, see examples/fd_redirection_demo.sh.
Rush now provides comprehensive support for positional parameters, enabling scripts to access and manipulate command-line arguments with full POSIX compliance:
$1, $2, $3, etc.$* and $@ provide access to all arguments as a single string$# returns the number of positional parameters as a stringshift [n] builtin command to manipulate parameter positions./rush-sh script.sh arg1 arg2Basic Usage:
# Create a script that uses positional parameters
cat > greet.sh << 'EOF'
#!/usr/bin/env rush-sh
echo "Hello $1!"
echo "You provided $# arguments"
echo "All arguments: $*"
EOF
# Make it executable and run with arguments
chmod +x greet.sh
./rush-sh greet.sh World
# Output: Hello World!
# You provided 1 arguments
# All arguments: World
Advanced Usage:
# Script with multiple arguments
cat > process.sh << 'EOF'
#!/usr/bin/env rush-sh
echo "Script name: $0"
echo "First arg: $1"
echo "Second arg: $2"
echo "Total args: $#"
# Shift parameters
echo "Shifting..."
shift
echo "New first arg: $1"
echo "New arg count: $#"
EOF
./rush-sh process.sh file1.txt file2.txt
# Output: Script name: process.sh
# First arg: file1.txt
# Second arg: file2.txt
# Total args: 2
# Shifting...
# New first arg: file2.txt
# New arg count: 1
**Running the Demo Script:**
To see all positional parameter features in action, run the demonstration script with multiple arguments:
```bash
./rush-sh examples/positional_parameters_demo.sh hello world test arguments
This will demonstrate:
$1, $2, $3, $4)$#)$*, $@)shift commandshift 2The script provides comprehensive output showing how each feature works with the provided arguments.
Parameter Manipulation:
# Using shift with custom count
cat > multi_shift.sh << 'EOF'
#!/usr/bin/env rush-sh
echo "Original args: $*"
echo "Count: $#"
# Shift by 2
shift 2
echo "After shift 2: $*"
echo "New count: $#"
EOF
./rush-sh multi_shift.sh a b c d e
# Output: Original args: a b c d e
# Count: 5
# After shift 2: c d e
# New count: 3
Key Features:
Integration with Other Features:
# Positional parameters with control structures
cat > check_args.sh << 'EOF'
#!/usr/bin/env rush-sh
if [ $# -eq 0 ]; then
echo "No arguments provided"
exit 1
fi
# Process each argument
for arg in $*; do
if [ -f "$arg" ]; then
echo "File: $arg"
elif [ -d "$arg" ]; then
echo "Directory: $arg"
else
echo "Other: $arg"
fi
done
EOF
./rush-sh check_args.sh /tmp /etc/passwd nonexistent
# Output: Directory: /tmp
# File: /etc/passwd
# Other: nonexistent
Implementation Details:
Rush now supports comprehensive POSIX sh parameter expansion with modifiers, providing powerful string manipulation capabilities directly in shell commands and scripts:
${VAR} - Simple variable expansion (equivalent to $VAR)${VAR:-default} - Use default if VAR is unset or null${VAR:=default} - Assign default if VAR is unset or null${VAR:+replacement} - Use replacement if VAR is set and not null${VAR:?error} - Display error if VAR is unset or null${VAR:offset} - Extract substring starting at offset${VAR:offset:length} - Extract substring with specified length${#VAR} - Get length of variable content${VAR#pattern} - Remove shortest match from beginning${VAR##pattern} - Remove longest match from beginning${VAR%pattern} - Remove shortest match from end${VAR%%pattern} - Remove longest match from end${VAR/pattern/replacement} - Replace first occurrence${VAR//pattern/replacement} - Replace all occurrences${!name} - Indirect variable reference (value of variable named by name)${!prefix*} and ${!prefix@} - Names of variables starting with prefixBasic Usage:
# Set a variable
MY_PATH="/usr/local/bin:/usr/bin:/bin"
# Default values
echo "Home: ${HOME:-/home/user}"
echo "Editor: ${EDITOR:-vim}"
# Assign default if unset
echo "Setting default..."
echo "Editor: ${EDITOR:=nano}"
# Alternative values
echo "Verbose: ${VERBOSE:+enabled}"
# Error handling
echo "Required var: ${REQUIRED_VAR:?This variable must be set}"
Substring Operations:
# Extract parts of strings
FILENAME="document.txt"
echo "Extension: ${FILENAME:9}" # "txt"
echo "Name only: ${FILENAME:0:8}" # "document"
# Length operations
echo "Length: ${#FILENAME}" # "13"
# Pattern-based length
LONG_STRING="hello world"
echo "Length: ${#LONG_STRING}" # "11"
Pattern Removal:
# Remove file extensions
FILENAME="document.txt"
echo "No extension: ${FILENAME%.txt}" # "document"
echo "No extension: ${FILENAME%%.txt}" # "document"
# Remove directory paths
FULL_PATH="/usr/bin/ls"
echo "Basename: ${FULL_PATH##*/}" # "ls"
echo "Directory: ${FULL_PATH%/*}" # "/usr/bin"
# Remove prefixes
PREFIXED="prefix_value"
echo "No prefix: ${PREFIXED#prefix_}" # "value"
Pattern Substitution:
# Replace substrings
GREETING="hello world"
echo "Replace first: ${GREETING/world/universe}" # "hello universe"
echo "Replace all: ${GREETING//l/L}" # "heLLo worLd"
# Multiple replacements
PATH_LIST="/usr/bin:/bin:/usr/local/bin"
echo "Clean path: ${PATH_LIST//:/ }" # "/usr/bin /bin /usr/local/bin"
Advanced Usage:
# Complex string manipulation
URL="https://example.com/path/to/resource"
echo "Domain: ${URL#*//}" # "example.com/path/to/resource"
echo "Domain: ${URL#*//}" | cut -d/ -f1 # "example.com"
echo "Path: ${URL#*/}" # "path/to/resource"
# Safe variable handling
CONFIG_FILE="/etc/app.conf"
echo "Config: ${CONFIG_FILE:-/etc/default.conf}"
# Indirect expansion - dynamic variable access
VAR_NAME="MESSAGE"
MESSAGE="Hello World"
echo "Indirect: ${!VAR_NAME}" # "Hello World"
# Indirect expansion - list matching variables
MY_VAR1="value1"
MY_VAR2="value2"
MY_VAR3="value3"
echo "All MY_ vars: ${!MY_*}" # "MY_VAR1 MY_VAR2 MY_VAR3"
Indirect Expansion:
# Basic indirect expansion - ${!name}
# Access variable whose name is stored in another variable
TARGET="HOME"
echo "Value: ${!TARGET}" # Expands to value of $HOME
# Practical use case - configuration selection
ENV="production"
production_db="prod.example.com"
development_db="dev.example.com"
DB_VAR="${ENV}_db"
echo "Database: ${!DB_VAR}" # "prod.example.com"
# Prefix-based indirect expansion - ${!prefix*}
# List all variables starting with a prefix
PATH_VAR1="/usr/bin"
PATH_VAR2="/usr/local/bin"
PATH_VAR3="/opt/bin"
echo "All PATH_ vars: ${!PATH_*}" # "PATH_VAR1 PATH_VAR2 PATH_VAR3"
# Works with both global and local variables
myfunc() {
local LOCAL_VAR1="a"
local LOCAL_VAR2="b"
echo "Local vars: ${!LOCAL_*}" # "LOCAL_VAR1 LOCAL_VAR2"
}
Integration with Other Features:
# Parameter expansion in control structures
FILENAME="test.txt"
if [ -f "${FILENAME%.txt}.bak" ]; then
echo "Backup exists for ${FILENAME%.txt}"
fi
# In arithmetic expressions
COUNT=42
echo "Count: $((COUNT + 1))"
# With command substitution
DIR_COUNT=$(find /tmp -type d | wc -l)
echo "Directories: ${DIR_COUNT:-0}"
# In case statements
case "${FILENAME##*.}" in
txt) echo "Text file" ;;
jpg|png) echo "Image file" ;;
*) echo "Other type" ;;
esac
Key Features:
Implementation Details:
Rush now provides comprehensive color support for enhanced terminal output with automatic detection and flexible configuration:
NO_COLOR=1 (accessibility standard) and RUSH_COLORS (explicit control)help, pwd, env with contextual coloringset_colors and set_color_scheme builtinsExample usage:
# Enable colors explicitly
export RUSH_COLORS=on
# Disable colors for accessibility
export NO_COLOR=1
# Switch color schemes
set_color_scheme dark
set_color_scheme light
set_color_scheme default
# Control colors dynamically
set_colors on
set_colors off
set_colors status # Show current status
Key Features:
NO_COLOR=1 environment variable for users who prefer monochrome outputRUSH_COLORS variable supports auto, on, off, 1, 0, true, false valuesColor Schemes:
Configuration Options:
# Environment variables
export NO_COLOR=1 # Disable colors (accessibility)
export RUSH_COLORS=auto # Auto-detect (default)
export RUSH_COLORS=on # Force enable
export RUSH_COLORS=off # Force disable
# Runtime commands
set_colors on # Enable colors
set_colors off # Disable colors
set_colors status # Show current status
set_color_scheme default # Standard colors
set_color_scheme dark # Dark theme
set_color_scheme light # Light theme
The color system is designed to be both powerful and unobtrusive, providing visual enhancements while respecting user preferences and accessibility needs.
Rush now provides comprehensive support for the POSIX set built-in command, enabling control over shell behavior through option flags and management of positional parameters:
- (enable) and + (disable) syntax-o optname or +o optname for long option namesset -- argsset or all options with set +o-e (errexit): Exit immediately if a command fails-u (nounset): Treat unset variables as errors-x (xtrace): Print commands before execution (with PS4 prefix and variable expansion)-v (verbose): Print shell input lines as read-n (noexec): Read commands but don't execute (syntax check mode)-f (noglob): Disable pathname expansion (globbing)-C (noclobber): Prevent output redirection from overwriting existing files (use >| to override)-a (allexport): Automatically export all variablesBasic Usage:
# Enable multiple options at once
set -eu # Enable errexit and nounset
# Display all shell options with their current state
set +o # Shows all options (on/off)
# Set positional parameters
set -- arg1 arg2 arg3 # Sets $1=arg1, $2=arg2, $3=arg3
# Clear positional parameters
set -- # Clears all positional parameters
# Named option syntax
set -o errexit # Enable errexit using long name
set +o nounset # Disable nounset using long name
# Display all shell variables
set # Shows all variables (NAME=value format)
Key Features:
set command-eux)-e) and long (-o errexit) forms supportedImplementation Details:
ShellState.options structure> from overwriting (use >| to override)The set built-in provides essential control over shell behavior, making scripts more robust and debugging easier while maintaining full POSIX compatibility.
Rush automatically sources a configuration file ~/.rushrc when starting in interactive mode, similar to bash's .bashrc. This allows you to customize your shell environment with:
Example ~/.rushrc file:
# Set environment variables
export EDITOR=vim
export PATH="$HOME/bin:$PATH"
# Create useful aliases
alias ll='ls -la'
alias ..='cd ..'
alias grep='grep --color=auto'
# Set custom variables
MY_PROJECTS="$HOME/projects"
WORKSPACE="$HOME/workspace"
# Display welcome message
echo "Welcome to Rush shell!"
echo "Type 'help' for available commands."
Key Features:
.rushrc files don't prevent shell startup.rushrc are available throughout the session.rushrc are handled gracefully~/.rushrc following Unix conventionsUsage Notes:
.rushrc are available to all subsequent commandsexport to make variables available to child processes#) are ignoredInstall rush-sh from crates.io:
cargo install rush-sh
Clone the repository:
git clone https://github.com/drewwalton19216801/rush-sh.git
cd rush-sh
Build the project:
cargo build --release
The binary will be available at target/release/rush-sh.
Run the shell without arguments to enter interactive mode:
./target/release/rush-sh
or
rush-sh
You'll see a prompt showing the condensed current working directory followed by $ (e.g., /h/d/p/r/rush-sh $) where you can type commands. Type exit to quit.
Configuration: Rush automatically sources ~/.rushrc on startup if it exists, allowing you to set up aliases, environment variables, and other customizations.
Execute commands from a file:
./target/release/rush-sh script.sh
or
rush-sh script.sh
The shell will read and execute each line from the script file. Note that when using script mode, shebang lines (e.g., #!/usr/bin/env bash) are not bypassed - they are executed as regular comments.
Execute a command string directly:
./target/release/rush-sh -c "echo Hello World"
or
rush-sh -c "echo Hello World"
The shell will execute the provided command string and exit.
The source (or .) built-in command provides a way to execute script files while bypassing shebang lines and comment lines that may specify other shells:
source script.sh
. script.sh
This is particularly useful for:
#!/usr/bin/env rush-sh shebangs#!/usr/bin/env bash) using rush insteadUnlike script mode (running ./target/release/rush-sh script.sh), the source command automatically skips shebang lines and comment lines, and executes all commands using the rush interpreter. Variables set in the sourced script are available in the parent shell.
ls -lals | grep txtecho "Hello" > hello.txtcd /tmppwdpushd /tmppopddirssource script.sh. script.shsource examples/basic_commands.shsource examples/elif_example.shsource examples/case_example.shsource examples/variables_example.shsource examples/until_demo.shsource examples/complex_example.shsource examples/positional_parameters_demo.shsource examples/functions_demo.shsource examples/return_demo.shalias ll='ls -l'; alias la='ls -la'aliasalias llunalias llll /tmpMY_VAR=hello; echo $MY_VARexport MY_VAR=value; env | grep MY_VARecho "Exit code: $?"; echo "PID: $$"NAME="John Doe"; echo "Hello $NAME"echo "First arg: $1, Second: $2"echo "You provided $# arguments"echo "All args: $*"shift; echo "New first: $1"shift 2; echo "After shift 2: $*"(cd /tmp && ls); pwd # Still in original directoryVAR=parent; (VAR=child; echo $VAR); echo $VAR # Shows parent(exit 42); echo $? # Shows 42(echo "Level 1"; (echo "Level 2"))(echo "output" > file.txt; cat file.txt) 2>errors.logif true; then echo yes; else echo no; fiif false; then echo no; elif true; then echo yes; else echo maybe; ficount=0; while [ $count -lt 5 ]; do echo "Count: $count"; count=$((count + 1)); donecount=0; until [ $count -eq 5 ]; do echo "Count: $count"; count=$((count + 1)); donecase hello in hello) echo match ;; *) echo no match ;; esaccase file.txt in *.txt) echo "Text file" ;; *.jpg) echo "Image" ;; *) echo "Other" ;; esaccase file in *.txt|*.md) echo "Document" ;; *.exe|*.bin) echo "Executable" ;; *) echo "Other" ;; esaccase letter in [abc]) echo "A, B, or C" ;; *) echo "Other letter" ;; esacfor i in 1 2 3; do echo "Number: $i"; donefor i in 1 2 3 4 5; do if [ $i -eq 3 ]; then break; fi; echo $i; donefor i in 1 2 3 4 5; do if [ $i -eq 3 ]; then continue; fi; echo $i; donefor i in 1 2; do for j in a b c; do if [ $j = b ]; then break 2; fi; echo "$i$j"; done; donesource examples/break_continue_demo.shmyfunc() { echo "Hello $1"; }myfunc worldlocal var="value"return 42declare -f myfuncif test -z "$VAR"; then echo "Variable is empty"; fiif [ -f "/etc/passwd" ]; then echo "File exists"; fiif test -n "$NAME" && [ -d "/tmp" ]; then echo "Ready"; fitest -x "invalid"; echo "Exit code: $?"echo "Current dir: $(pwd)"echo "Files:ls | wc -l"PROJECT_DIR="$(pwd)/src"echo "Rust version: $(rustc --version | cut -d' ' -f2)"RESULT="$(nonexistent_command 2>/dev/null || echo 'failed')"$(echo hello | grep ll) > output.txtecho "Output: $(echo 'First'; echo 'Second')"echo "Result: $((2 + 3 * 4))"result=$((x * y + z))if [ $((count % 2)) -eq 0 ]; then echo "Even"; fiarea=$((length * width))fahrenheit=$((celsius * 9 / 5 + 32))echo "Home: ${HOME:-/home/user}"echo "Extension: ${FILENAME:9}"echo "Basename: ${FULL_PATH##*/}"echo "Replaced: ${TEXT/old/new}"echo "Length: ${#VARIABLE}"echo "Value: ${!VAR_NAME}" and echo "Vars: ${!PREFIX*}"cat << EOF (multi-line input)grep pattern <<< "search text" (single-line input)echo {a,b,c} β a b cecho {1..5} β 1 2 3 4 5echo {a..c} β a b cecho file{1,2,3}.txt β file1.txt file2.txt file3.txtecho {{a,b},{c,d}} β a b c decho {a,b}{1,2} β a1 a2 b1 b2mkdir -p project/{src,test,docs}touch file{1..10}.txtcommand 2>errors.logcat 3<input.txtcommand 2>>errors.logcommand 2>&1 (combine stderr into stdout)command 2>&- (close stderr)cat 3<>file.txtcommand >out.txt 2>err.txt 3>custom.txt./script.sh >output.log 2>errors.logcommand >/dev/null 2>&1source examples/fd_redirection_demo.shcd β cd, env, exitcat f β cat file.txtcd src/ β cd src/main/l β ls, g β grepls src/m β ls src/main/Rush features a modular architecture with well-organized components for maintainability and clarity:
Lexer (src/lexer/):
mod.rs): Token recognition, quote handling, variable detection, alias expansion, command substitution preservation, here-document tokenization, and FD redirection parsingtoken.rs): Token enum definitions and helper methodstests/): 7 focused test modules covering basic tokenization, alias expansion, quote handling, expansion patterns, redirection operators, tilde expansion, and edge casesParser (src/parser/):
mod.rs): AST construction, pipeline building, redirection parsing, subshell parsing, and FD redirection AST nodesast.rs): Complete AST node type definitions for commands, pipelines, and control flow structurescontrol_flow.rs): Specialized parsers for if/elif/else, case, for, while, until, and function definitionstests/): 6 focused test modules covering basic parsing, control flow, compound commands, pipelines, operators, and redirectionsExecutor (src/executor/):
mod.rs): Command execution engine and error propagationexpansion.rs): Variable expansion, wildcard expansion, and command substitutionredirection.rs): FD table management, redirection handling, and here-document processingcommand.rs): Single command execution, pipeline management, and built-in integrationsubshell.rs): Subshell execution with state isolation, compound commands, and trap inheritancetests/): 5 focused test modules covering execution, expansion, redirection, commands, and subshellsState Management (src/state/):
mod.rs): Variable scoping, environment integration, function context, directory stack, alias management, and loop control statefd_table.rs): File descriptor table with save/restore capabilities and FD operationsoptions.rs): Shell option flags (errexit, nounset, xtrace, etc.) and option displaysignals.rs): Trap management, signal normalization, and trap displaytests/): 4 focused test modules covering state management, variable scoping, FD operations, and shell optionssrc/arithmetic.rs): $((...)) evaluation using Shunting-yard algorithm with comprehensive operator supportsrc/parameter_expansion.rs): ${VAR:-default} and modifier processing with indirect expansion supportsrc/brace_expansion.rs): {a,b,c} and range expansion ({1..5}) with nested pattern supportsrc/builtins/): 27 optimized built-in commands with direct state accesssrc/completion.rs): Intelligent tab-completion for commands, files, and directoriessrc/script_engine.rs): Script file execution with proper error handlingThe modular refactoring (completed January 2026) transformed four monolithic modules into well-organized structures:
clap: For command-line argument parsing with derive macros.rustyline: For interactive line editing and history with signal handling support.signal-hook: For robust signal handling (SIGINT, SIGTERM).glob: For pattern matching in case statements and wildcard expansion.lazy_static: For global state management in tab completion.Rush includes an extensive test suite with 499+ test functions ensuring reliability and correctness:
Test Coverage Areas:
Run the complete test suite with:
Run all tests with:
cargo test
Run specific test modules:
cargo test builtins
cargo test completion
cargo test executor
cargo test lexer
cargo test main
cargo test parser
cargo test state
cargo test integration
Rush includes a comprehensive performance benchmark suite for measuring and tracking shell performance across all major components:
Run the complete benchmark suite from the repository root:
cargo run -p rush-benchmarks
This will execute 20+ benchmark scenarios covering:
The benchmark suite generates:
target/benchmark_report.htmltarget/benchmark_results.jsonπ Rush Shell Performance Benchmark Suite
==========================================
π Registering lexer benchmarks...
π Registering parser benchmarks...
β‘ Registering executor benchmarks...
π Registering expansion benchmarks...
ποΈ Registering control structure benchmarks...
π Registering pipeline benchmarks...
π Registering script benchmarks...
π Running benchmarks...
Running: lexer_basic_tokens (Basic tokenization (simple commands))
Running: lexer_complex_tokens (Complex tokenization (quotes, variables, expansions))
...
π Generating report...
β
Benchmark completed!
π Results summary:
Total benchmarks: 21
Total time: 2.34s
π Detailed report saved to: target/benchmark_report.html
π JSON results saved to: target/benchmark_results.json
Run benchmarks with custom iteration counts:
# Use the library API for custom configurations
# See benchmarks/src/main.rs for implementation details
View the generated HTML report in a browser:
# Open target/benchmark_report.html in your browser
# or serve it locally:
python3 -m http.server 8000 -d target/
# Then visit http://localhost:8000/benchmark_report.html
The benchmark suite covers all major shell components:
The benchmark suite is designed for:
This benchmark suite provides a foundation for maintaining optimal shell performance and identifying performance regressions during development.
The test suite provides extensive coverage of:
$(...) and `...` syntax, error handling, variable expansion)$((...)) syntax, operator precedence, variable integration, error handling)$1, $2, $*, $@, $#, shift command)${VAR:-default}, ${VAR#pattern}, ${VAR/pattern/replacement}, etc.)<< and <<< with proper expansion handling)Contributions are welcome! Please fork the repository, make your changes, and submit a pull request.
This project is licensed under the MIT License. See LICENSE.txt for details.