From b25884b5e08e81826b13319c792efb6b71e47aa8 Mon Sep 17 00:00:00 2001 From: exlier <290591388+exlier@users.noreply.github.com> Date: Mon, 20 Jul 2026 10:27:02 +0530 Subject: [PATCH] Revise README.md for clarity and updates Updated the README.md to reflect the latest changes, including a new overview, installation instructions, usage examples, and a roadmap for future features. --- README.md | 956 ++++++++++++++++++------------------------------------ 1 file changed, 308 insertions(+), 648 deletions(-) diff --git a/README.md b/README.md index 129dfe8..5ac4f2d 100644 --- a/README.md +++ b/README.md @@ -1,833 +1,493 @@ -# 🐄 TruShell -**TruShell** is an interactive shell environment designed to integrate task tracking and time management tools seamlessly with traditional terminal commands. Built in Rust with a custom expression parser, TruShell extends the Unix philosophy by providing a unified interface where productivity features and system commands coexist naturally. - ---- - -## TABLE OF CONTENTS - -1. [Overview](#overview) -2. [Architecture](#architecture) -3. [Installation & Building](#installation--building) -4. [Usage](#usage) -5. [Language Features](#language-features) -6. [Module Reference](#module-reference) -7. [Parsing System](#parsing-system) -8. [Command Execution](#command-execution) -9. [Examples](#examples) -10. [Development](#development) - ---- - -## OVERVIEW - -TruShell is not a replacement shell but rather a **productivity layer** that bridges the gap between system administration and personal task management. It runs as an interactive REPL (Read-Eval-Print Loop) that: - -- Accepts and executes ordinary shell commands (`ls`, `cd`, `grep`, etc.) -- Parses and interprets custom expressions for task and time operations -- Maintains compatibility with existing Unix tools through fallback command execution -- Provides a consistent interface for both system-level and productivity-level operations - -### Key Features - -- **Hybrid Parsing**: Intelligently distinguishes between shell commands and custom expressions -- **Expression Evaluation**: Supports arithmetic, comparisons, variables, pipelines, and redirects -- **Pipeline Support**: Chain operations together using the pipe operator (`|`) -- **Redirect Support**: Handle command redirection with `>`, `>>`, `<`, and `&>` for both standalone commands and pipeline stages -- **Task Integration**: Foundation for task tracking and time management (future expansion) -- **Graceful Fallback**: Executes as system commands if parsing fails - ---- - -## ARCHITECTURE - -TruShell follows a modular, layered architecture typical of interpreted languages: ``` -┌─────────────────────────────────────────┐ -│ Interactive REPL (main.rs) │ -│ • User Input Loop │ -│ • Command/Expression Routing │ -│ • Fallback Execution │ -└──────────────┬──────────────────────────┘ - │ - ┌───────┴────────┐ - │ │ -┌──────▼──────┐ ┌──────▼──────────┐ -│ Lexer │ │ Parser │ -│ (Tokenize) │ │ (AST Build) │ -└─────────────┘ └─────────────────┘ - │ │ - └───────┬────────┘ - │ - ┌──────▼──────────┐ - │ AST Nodes │ - │ (Expressions) │ - └─────────────────┘ - │ - ┌──────▼──────────────────┐ - │ Command Execution │ - │ • System Calls │ - │ • Process Management │ - └─────────────────────────┘ +████████████████████████████████████████████████████████████████████████ +█ █ +█ ████████╗██████╗ ██╗ ██╗███████╗██╗ ██╗███████╗██╗ ██╗ █ +█ ╚══██╔══╝██╔══██╗██║ ██║██╔════╝██║ ██║██╔════╝██║ ██║ █ +█ ██║ ██████╔╝██║ ██║███████╗███████║█████╗ ██║ ██║ █ +█ ██║ ██╔══██╗██║ ██║╚════██║██╔══██║██╔══╝ ██║ ██║ █ +█ ██║ ██║ ██║╚██████╔╝███████║██║ ██║███████╗███████╗███████╗ █ +█ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ █ +█ █ +█ █ +█ The Next-Generation Shell █ +█ Built in Rust for Performance █ +█ █ +████████████████████████████████████████████████████████████████████████ ``` -### Design Philosophy - -1. **Separation of Concerns**: Lexing, parsing, and execution are distinct phases -2. **Error Resilience**: Parse failures trigger fallback to system command execution -3. **Minimal Dependencies**: Uses only `crossterm` for terminal handling -4. **Extensibility**: AST-based design allows easy addition of new expression types +# TruShell ---- +A general-purpose shell written in Rust. Like Bash and Zsh, but with modern syntax and task management baked in. -## INSTALLATION & BUILDING +Status: Alpha (actively developing) -### Prerequisites +--- -- **Rust 1.70+** (MSRV: Edition 2021) -- **Cargo** (Rust's package manager) +## QUICK START -### Building from Source +### Installation ```bash -git clone https://github.com/TruFoundation/TruShell.git -cd TruShell -cargo build --release +$ git clone https://github.com/TruFoundation/TruShell.git +$ cd TruShell +$ cargo build --release +$ ./target/release/trushell ``` -The compiled binary will be located at `target/release/trushell`. - -### Running +Or run directly: ```bash -./target/release/trushell +$ cargo run ``` -Or directly via Cargo: +### Your First Commands ```bash -cargo run +Welcome to TruShell Native Engine +trushell> pwd +/home/user/projects + +trushell> ls -la +total 48 +drwxr-xr-x 5 user staff 160 Jul 5 12:34 . +-rw-r--r-- 1 user staff 1234 Jul 05 12:30 README.md + +trushell> let x = 42 +trushell> let result = $x * 2 ``` --- -## USAGE +## WHAT IS TRUSHELL? -### Interactive Session +TruShell is a modern shell that: -Upon startup, TruShell displays a welcome message and enters a prompt loop: +- Runs standard Unix commands: ls, cat, grep, cd, etc. +- Understands expressions: arithmetic, variables, comparisons +- Chains operations: pipes, redirects, filters +- Manages tasks: integrate time tracking and task management (coming soon) +- Written in Rust: fast, safe, and reliable -``` -Welcome to TruShell Native Engine -trushell ❯ -``` +Think of it as Bash meets a modern expression language. You get the power of the shell with cleaner, more intuitive syntax. -### Exit Commands +--- -- **`exit`**: Gracefully shut down the shell -- **`Ctrl+D`** (EOF): Safely terminate the shell +## FEATURES -### Basic Operations +### Interactive REPL -#### System Commands +Just like your favorite shell, TruShell reads input, evaluates it, prints output, and loops: -Execute any command available in your PATH: +```bash +trushell> echo "Hello, World!" +Hello, World! -``` -trushell ❯ ls -la -trushell ❯ pwd -trushell ❯ echo "Hello, World!" +trushell> exit +Goodbye! ``` -#### Directory Navigation +### Variables and Expressions -``` -trushell ❯ cd /tmp -trushell ❯ cd ~ -``` +```bash +# Declare variables with 'let' +trushell> let name = "Alice" +trushell> let age = 30 -The `cd` command is handled specially to modify TruShell's working directory (not spawned as a subprocess). +# Use variables with $ +trushell> let next_year_age = $age + 1 -#### Variable Assignment +# Arithmetic +trushell> let sum = 10 + 5 +trushell> let product = 3 * 7 +``` -Define variables using `let`: +### Comparisons and Logic +```bash +trushell> let is_adult = $age > 18 +trushell> let is_match = "hello" == "hello" +trushell> let not_empty = "text" != "" ``` -trushell ❯ let x = 42 -trushell ❯ let name = "Alice" -trushell ❯ let flag = true -``` - -#### Expressions -Perform arithmetic and logical operations: +### Number Units -``` -trushell ❯ let result = 10 + 5 -trushell ❯ let product = 3 * 7 -trushell ❯ let ratio = 100 / 4 +```bash +# Numbers can have units for readability +trushell> let file_size = 1mb +trushell> let timeout = 500ms ``` -#### Comparisons +### Pipes and Redirects -``` -trushell ❯ let is_big = 42 > 10 -trushell ❯ let is_equal = 5 == 5 -trushell ❯ let not_empty = "text" != "" -``` +```bash +# Chain commands with pipes +trushell> cat data.txt | grep "error" -#### Pipelines +# Redirect output to files +trushell> echo "Hello" > greeting.txt +trushell> echo "World" >> greeting.txt -Chain operations together using `|`: +# Redirect stdin +trushell> cat < input.txt > output.txt +# Combine stdout and stderr +trushell> command &> log.txt ``` -trushell ❯ ls() | filter { $it.size > 1mb } -``` - -#### Redirects -Redirect command input/output and combine streams: +### Code Blocks -``` -trushell ❯ echo hello > out.txt -trushell ❯ echo append >> out.txt -trushell ❯ cat < in.txt -trushell ❯ echo hello | cat > out.txt -trushell ❯ echo error &> error.log +```bash +# Group statements in blocks +trushell> let data = { let x = 5; let y = 10; $x + $y } ``` --- -## LANGUAGE FEATURES - -### Token Types +## HOW IT WORKS -TruShell's lexer recognizes the following token categories: +TruShell uses a classic interpreter pipeline: -| Token Class | Examples | Purpose | -|-------------|----------|---------| -| **Keywords** | `let`, `true`, `false` | Language control structures | -| **Identifiers** | `x`, `$var`, `_private` | Variable and function names | -| **Numbers** | `42`, `3mb`, `100kb` | Numeric literals with optional units | -| **Strings** | `"hello"` | Quoted string literals | -| **Flags** | `-la`, `--verbose`, `--help` | Command-line flags (preserved) | -| **Operators** | `+`, `-`, `*`, `/`, `>`, `<`, `==`, `!=` | Binary operations | -| **Delimiters** | `()`, `{}`, `[]`, `.`, `,`, `;` | Structure and grouping | -| **Pipes** | `\|` | Pipeline sequencing | +``` +┌─────────────────────────────────────────┐ +│ User Input (REPL) │ +├─────────────────────────────────────────┤ +│ Lexer: Convert text -> tokens │ +├─────────────────────────────────────────┤ +│ Parser: Convert tokens -> AST │ +├─────────────────────────────────────────┤ +│ Executor: Run AST or fallback to shell │ +├─────────────────────────────────────────┤ +│ Output / Side Effects │ +└─────────────────────────────────────────┘ +``` -### Data Types +### Example: Parsing 'let x = 5 + 3' -TruShell supports the following literal types: +Tokenize: +``` +[let, x, =, 5, +, 3] +``` -```rust -pub enum Literal { - Number { value: i64, unit: Option }, // 42, 1mb, 500ms - String(String), // "text" - Boolean(bool), // true, false +Parse: +``` +Let { + name: "x", + value: BinaryOp { + left: 5, + op: Add, + right: 3 + } } ``` -### Binary Operators - -| Operator | Type | Precedence | Example | -|----------|------|------------|---------| -| `+` | Addition | Term | `5 + 3` | -| `-` | Subtraction | Term | `10 - 4` | -| `*` | Multiplication | Factor | `3 * 4` | -| `/` | Division | Factor | `12 / 3` | -| `>` | Greater Than | Comparison | `5 > 3` | -| `<` | Less Than | Comparison | `2 < 5` | -| `>=` | Greater or Equal | Comparison | `5 >= 5` | -| `<=` | Less or Equal | Comparison | `3 <= 5` | -| `==` | Equals | Comparison | `5 == 5` | -| `!=` | Not Equals | Comparison | `3 != 5` | - -### Operator Precedence - -TruShell follows standard mathematical precedence, evaluated in this order (lowest to highest): - -1. **Comparison Operators** (`>`, `<`, `>=`, `<=`, `==`, `!=`) -2. **Term Operators** (`+`, `-`) -3. **Factor Operators** (`*`, `/`) -4. **Primary** (Literals, Identifiers, Parentheses, Blocks) - -### Variables - -Variables are declared with `let` and referenced with `$`: - +Execute: ``` -trushell ❯ let count = 10 -trushell ❯ let doubled = $count * 2 +Variable x is now 8 ``` -Variables starting with `$` are treated as **Variable tokens** and can be accessed in expressions. +--- -### Blocks +## COMMAND REFERENCE -Code blocks are enclosed in `{}` and contain semicolon-separated statements: +### Built-in Commands -``` -trushell ❯ let data = { let x = 5; let y = 10; $x + $y } -``` +| Command | Syntax | Description | +|---------|--------|-------------| +| let | let name = expression | Declare a variable | +| exit | exit | Leave the shell (or Ctrl+D) | +| cd | cd path | Change directory | ---- +### Operators -## MODULE REFERENCE +Arithmetic: +- '+' Add +- '-' Subtract +- '*' Multiply +- '/' Divide -### `main.rs` — Interactive REPL & Command Execution +Comparison: +- '>' Greater than +- '<' Less than +- '>=' Greater or equal +- '<=' Less or equal +- '==' Equal +- '!=' Not equal -**Purpose**: Orchestrates the shell's interactive loop and manages command execution. +Input/Output: +- '|' Pipe output to next command +- '>' Write to file (overwrite) +- '>>' Append to file +- '<' Read from file +- '&>' Redirect stderr and stdout -#### Main Components +--- -##### `fn main()` -- Initializes the shell with a welcome message -- Enters an infinite loop reading user input -- Routes input to the appropriate handler (exit, cd, parse, or fallback) +## EXAMPLES -**Key Invariants**: -- Reads lines until EOF (`Ctrl+D`) or explicit `exit` command -- Maintains current working directory for the shell process -- Handles all I/O errors gracefully with user-friendly messages +### Navigation -##### `fn execute_system_command(cmd: &str, args: &[&str])` -- Spawns a new process for the given command -- Inherits stdin, stdout, stderr for seamless integration -- Reports execution errors with descriptive messages +```bash +trushell> cd /tmp +trushell> pwd +/tmp -**Execution Flow**: -``` -Command::new(cmd) - └─ .args(args) - └─ .stdin(Stdio::inherit()) - └─ .stdout(Stdio::inherit()) - └─ .stderr(Stdio::inherit()) - └─ .spawn() - └─ .wait() +trushell> cd ~ +trushell> pwd +/home/user ``` -##### `fn probable_cli_from_ast(ast: &parser::ASTNode) -> Option<(String, Vec)>` -- **Heuristic Detection**: Attempts to interpret parsed AST as a CLI invocation -- **Use Case**: Handles cases where `ls -la` is parsed as `ls - la` (subtraction) -- **Strategy**: - 1. Traverses the AST looking for a chain of subtraction operations - 2. Extracts the leftmost node as the command name - 3. Collects remaining identifiers/strings as arguments - 4. Returns `Some((cmd, args))` if the pattern matches, otherwise `None` +### File Operations -**Example Transformation**: -``` -Input: "ls -la" -Parse: BinaryOp { left: Identifier("ls"), op: Subtract, right: Literal(String("-la")) } -Extract: ("ls", ["-la"]) -Execute: ls -la +```bash +trushell> ls -la +trushell> cat README.md | head -20 +trushell> grep "error" *.log > errors.txt +trushell> cp file.txt backup.txt ``` ---- +### Calculations -### `parser.rs` — Lexing & Parsing Engine - -**Purpose**: Converts raw user input into an Abstract Syntax Tree (AST) for interpretation. - -#### Token Definitions - -```rust -pub enum Token { - Let, // Variable declaration - Flag(String), // CLI flags (-la, --help) - Identifier(String), // Variable/function names - Number(String), // Numeric literals - StringLiteral(String), // Quoted strings - Boolean(bool), // true/false - Equals, // = assignment - Pipe, // | pipeline - LParen, RParen, // ( ) - LBrace, RBrace, // { } - Dot, // . property access - Comma, // , separator - Semicolon, // ; statement terminator - GreaterThan, // > - LessThan, // < - GreaterThanOrEqual, // >= - LessThanOrEqual, // <= - EqualsEquals, // == - BangEquals, // != - Plus, // + - Minus, // - - Star, // * - Slash, // / -} +```bash +trushell> let bytes = 1024 +trushell> let kilobytes = $bytes / 1024 +trushell> let total = 10 + 20 + 30 + 40 ``` -#### AST Node Types - -```rust -pub enum ASTNode { - Let { name: String, value: Box }, - Pipeline { stages: Vec> }, - Command { name: String, args: Vec }, - Redirect { source: Box, fd: u8, mode: RedirectMode, target: RedirectTarget, merge_stderr: bool }, - Block { body: Vec }, - BinaryOp { left: Box, op: BinaryOperator, right: Box }, - Variable(String), - Literal(Literal), - PropertyAccess { target: Box, property: String }, - Identifier(String), -} +### Conditional Logic + +```bash +trushell> let threshold = 100 +trushell> let value = 150 +trushell> let exceeds = $value > $threshold +# exceeds is now true ``` -#### Lexer (`struct Lexer`) +### Complex Expressions -**Responsibility**: Converts a string into a sequence of tokens. +```bash +trushell> let x = 10 +trushell> let y = 20 +trushell> let z = $x + $y * 2 +# z is 50 (multiplication happens first) -##### Tokenization Rules +trushell> let result = ($x + $y) * 2 +# result is 60 +``` -1. **Whitespace**: Skipped entirely -2. **Identifiers**: Start with `a-z`, `A-Z`, `_`, or `$`; continue with alphanumerics or `_` -3. **Keywords**: `let`, `true`, `false` → special tokens -4. **Numbers**: Digits optionally followed by a unit string (e.g., `5`, `100ms`, `1mb`) -5. **Strings**: Double-quoted; no escape sequences currently supported -6. **Flags**: `-` followed by letters/hyphens (e.g., `-la`, `--help`) -7. **Operators**: Single and multi-character (`==`, `!=`, `>=`, `<=`) +--- -##### Special Flag Handling +## SYNTAX -The lexer recognizes CLI flags intelligently: -```rust -if let Some(second) = peek_two_chars_ahead { - if second.is_alphabetic() || second == '-' { - // Lex as a flag (e.g., -la, --verbose) - self.lex_flag() - } else { - // Lex as minus operator (e.g., 5 - 3) - Token::Minus - } -} -``` +### Tokens -**Effect**: `ls-la` is lexed as a command followed by a flag, not as subtraction. +TruShell recognizes the following token types: -#### Parser (`struct Parser`) +| Token Class | Examples | Purpose | +|-------------|----------|---------| +| Keywords | let, true, false | Language control | +| Identifiers | x, $var, _private | Variable and function names | +| Numbers | 42, 3mb, 100kb | Numeric literals with optional units | +| Strings | "hello" | Quoted string literals | +| Flags | -la, --verbose, --help | Command-line flags | +| Operators | +, -, *, /, >, <, ==, != | Binary operations | +| Delimiters | (), {}, [], ., ,, ; | Structure and grouping | +| Pipes | \| | Pipeline sequencing | -**Responsibility**: Converts tokens into an AST using recursive descent parsing. +### Data Types -##### Parsing Precedence (Lowest to Highest) +TruShell supports the following literal types: ``` -parse_statement - ├─ if let: parse_let_statement - └─ else: parse_pipeline +Number - Integer values, optionally with units (42, 1mb, 500ms) +String - Double-quoted text literals ("text") +Boolean - true or false values +``` -parse_pipeline - └─ parse_expression (with | separator) +### Operator Precedence -parse_expression - └─ parse_comparison +Operators are evaluated in this order (lowest to highest): -parse_comparison (>/=/<=,==,!=) - └─ parse_term +1. Comparison Operators (>, <, >=, <=, ==, !=) +2. Term Operators (+, -) +3. Factor Operators (*, /) +4. Primary (Literals, Identifiers, Parentheses, Blocks) -parse_term (+,-) - └─ parse_factor +### Variables -parse_factor (*,/) - └─ parse_primary +Variables are declared with 'let' and referenced with '$': -parse_primary (literals, identifiers, parens, blocks) - └─ parse_identifier_expression (handles ., (, {}) +```bash +trushell> let count = 10 +trushell> let doubled = $count * 2 ``` -##### Let Statement Parsing - -```rust -let x = 5 -├─ Token::Let -├─ expect identifier → "x" -├─ expect = -└─ parse_expression → Literal(Number(5)) - -Result: ASTNode::Let { - name: "x", - value: Box::new(Literal(Number(5))) -} -``` +--- -##### Pipeline Parsing +## ARCHITECTURE -```rust -ls() | filter { $it.size > 1mb } -├─ parse_expression → Command { name: "ls", args: [] } -├─ Token::Pipe -├─ parse_expression → Command { name: "filter", args: [Block {...}] } -└─ Token::Pipe (none) +### Project Structure -Result: ASTNode::Pipeline { - stages: [Command{...}, Command{...}] -} ``` - -##### Number Literal Parsing - -Numbers can include units (e.g., `5mb`, `100ms`): - -```rust -pub fn parse_number_literal(raw: &str) -> Result { - let digits: String = raw.chars().take_while(|ch| ch.is_ascii_digit()).collect(); - let unit: String = raw.chars().skip_while(|ch| ch.is_ascii_digit()).collect(); - - Ok(Literal::Number { - value: digits.parse::()?, - unit: if unit.is_empty() { None } else { Some(unit) }, - }) -} +TruShell/ +├── src/ +│ ├── main.rs - REPL and command execution +│ └── parser.rs - Lexer and parser +├── Cargo.toml - Project manifest +├── Cargo.lock - Dependency lock file +└── README.md - This file ``` -**Examples**: -- `5` → `Number { value: 5, unit: None }` -- `1mb` → `Number { value: 1, unit: Some("mb") }` -- `100ms` → `Number { value: 100, unit: Some("ms") }` - ---- - -## PARSING SYSTEM - -### Input Flow +### Parsing Flow ``` User Input String ↓ -[Lexer::tokenize()] +Lexer::tokenize() ↓ Token Vector ↓ -[Parser::parse_statement()] +Parser::parse_statement() ↓ ASTNode (Abstract Syntax Tree) ↓ -[main.rs execution logic] +Execution logic ↓ Output/Side Effects ``` -### Example: Parsing `let x = 5 + 3` - -**Input**: `"let x = 5 + 3"` - -**Step 1: Tokenization** -``` -[Let, Identifier("x"), Equals, Number("5"), Plus, Number("3")] -``` - -**Step 2: Parsing (Recursive Descent)** -``` -parse_statement - └─ parse_let_statement - ├─ expect Let → ✓ - ├─ expect_identifier → "x" - ├─ expect Equals → ✓ - └─ parse_expression (for "5 + 3") - └─ parse_comparison - └─ parse_term - ├─ parse_factor → Literal(5) - ├─ detect Plus - ├─ parse_factor → Literal(3) - └─ combine: BinaryOp { left: 5, op: Add, right: 3 } -``` - -**Step 3: AST Result** -```rust -ASTNode::Let { - name: "x", - value: Box::new( - ASTNode::BinaryOp { - left: Box::new(Literal(Number { value: 5, unit: None })), - op: Add, - right: Box::new(Literal(Number { value: 3, unit: None })) - } - ) -} -``` - -### Error Handling - -The parser provides descriptive error messages: - -```rust -pub struct ParseError { - pub message: String, -} -``` +### Design Philosophy -**Common Errors**: -- `"Expected identifier, found ..."` -- `"Unexpected token in expression"` -- `"Unterminated string literal"` -- `"Unexpected character: '...'"` (from lexer) +1. Separation of Concerns: Lexing, parsing, and execution are distinct phases +2. Error Resilience: Parse failures trigger fallback to system command execution +3. Minimal Dependencies: Uses only crossterm for terminal handling +4. Extensibility: AST-based design allows easy addition of new expression types --- -## COMMAND EXECUTION +## EXECUTION MODEL -### Execution Flow in `main()` +### Command Routing -``` -loop { - 1. Read user input - 2. Trim whitespace - 3. Check for special commands: - ├─ "exit" → break loop - └─ "cd ..." → change directory - 4. Attempt to parse: - ├─ Success → check if it's a probable CLI command - │ ├─ Yes → execute as system command - │ └─ No → print AST (debug mode) - └─ Failure → fallback to system command execution - 5. Display output -} -``` +When you enter a command, TruShell: -### Special Command Handling +1. Reads the input line +2. Checks for special commands (exit, cd) +3. Attempts to parse it +4. If parse succeeds, checks if it's a recognized pattern +5. If not recognized, falls back to executing as a system command -#### `exit` -Terminates the shell gracefully: -```rust -if trimmed_input == "exit" { - println!("Goodbye!"); - break; -} -``` +### Special Commands -#### `cd` (Change Directory) -Handled specially without spawning a subprocess: -```rust -if trimmed_input.starts_with("cd") { - let parts: Vec<&str> = trimmed_input.split_whitespace().collect(); - let new_dir = parts.get(1).copied().unwrap_or("."); - if let Err(e) = std::env::set_current_dir(new_dir) { - eprintln!("trushell: cd: {}: {}", new_dir, e); - } - continue; -} -``` +exit - Terminates the shell gracefully + +cd path - Changes the current directory (handled specially, not as a subprocess) ### Fallback Execution -When parsing fails or the AST doesn't match a known pattern, TruShell falls back to executing the input as a system command: +If parsing fails, TruShell executes the input as a system command. This means most Unix commands work transparently: -```rust -Err(err) => { - eprintln!("Parse error: {}", err); - let parts: Vec<&str> = trimmed_input.split_whitespace().collect(); - let command = parts[0]; - let args = &parts[1..]; - execute_system_command(command, args); -} +```bash +trushell> grep pattern file.txt +trushell> find . -name "*.rs" +trushell> ps aux | less ``` -**Result**: Most Unix commands work transparently even if parsing fails. - -### Redirect and Pipeline Execution - -TruShell now supports shell-style redirection for parsed commands, including standalone redirects and redirects on pipeline stages. The execution engine resolves redirect AST nodes before spawning processes and correctly wires command stdin/stdout for pipes: +### Pipes and Redirects -- `cmd > file` writes stdout to a file -- `cmd >> file` appends stdout to a file -- `cmd < file` reads stdin from a file -- `cmd &> file` redirects stderr to the same target file -- `cmd | other > file` pipes data into a redirected final stage +TruShell supports shell-style redirection: -This integration keeps parsed AST behavior aligned with traditional shell semantics while preserving the existing fallback execution model. +- 'cmd > file' writes stdout to a file +- 'cmd >> file' appends stdout to a file +- 'cmd < file' reads stdin from a file +- 'cmd &> file' redirects stderr to the same target file +- 'cmd | other > file' pipes data into a redirected final stage -### Process Management - -Commands are executed with inherited I/O streams: - -```rust -Command::new(cmd) - .args(args) - .stdin(Stdio::inherit()) // User input reaches subprocess - .stdout(Stdio::inherit()) // Subprocess output visible - .stderr(Stdio::inherit()) // Errors displayed directly - .spawn() - .wait() -``` +This integration keeps parsed AST behavior aligned with traditional shell semantics. --- -## EXAMPLES - -### Basic Arithmetic - -```bash -trushell ❯ let x = 10 -Parsed AST: Let { name: "x", value: ... } +## DEVELOPMENT -trushell ❯ let y = $x * 2 -Parsed AST: Let { name: "y", value: ... } +### Requirements -trushell ❯ let z = 100 / 5 -Parsed AST: Let { name: "z", value: ... } -``` +- Rust 1.70 or later (Edition 2021) +- Cargo (comes with Rust) -### Variable Usage +### Building +Debug build: ```bash -trushell ❯ let name = "Alice" -trushell ❯ let greeting = "Hello, " + $name -Parsed AST: Let { name: "greeting", value: ... } +$ cargo build ``` -### Comparisons - +Release build (optimized): ```bash -trushell ❯ let is_adult = 25 > 18 -Parsed AST: Let { name: "is_adult", value: - BinaryOp { - left: 25, - op: GreaterThan, - right: 18 - } -} - -trushell ❯ let in_range = 50 >= 10 +$ cargo build --release ``` -### System Commands - +Run tests: ```bash -trushell ❯ ls -la -total 48 -drwxr-xr-x 5 user group 160 Jul 5 12:34 . -drwxr-xr-x 10 user group 320 Jul 4 18:22 .. --rw-r--r-- 1 user group 1234 Jul 05 12:30 README.md -... - -trushell ❯ pwd -/home/user/projects/TruShell - -trushell ❯ echo "Building..." -Building... +$ cargo test ``` -### Directory Navigation - -```bash -trushell ❯ cd /tmp -trushell ❯ pwd -/tmp -trushell ❯ cd - -trushell ❯ pwd -/home/user/projects/TruShell -``` - -### Pipelines (Future Use) - +Run with debugging: ```bash -trushell ❯ ls() | filter { $it.size > 1mb } -Parsed AST: Pipeline { - stages: [ - Command { name: "ls", args: [] }, - Command { name: "filter", args: [Block { ... }] } - ] -} +$ RUST_BACKTRACE=1 cargo run ``` ---- - -## DEVELOPMENT +### Code Guidelines -### Project Structure +- Use 'cargo fmt' for formatting +- Run 'cargo clippy' to catch common mistakes +- Add unit tests for new features +- Update docs if behavior changes -``` -TruShell/ -├── Cargo.toml # Rust project manifest -├── Cargo.lock # Dependency lock file -├── src/ -│ ├── main.rs # REPL and command execution (4.3 KB) -│ └── parser.rs # Lexer and parser (19.0 KB) -├── target/ # Compiled binaries (excluded from repo) -├── README.md # This file -└── LICENSE.md # Project license -``` - -### Dependencies - -- **crossterm** (v0.27): Terminal manipulation and event handling -- **Standard Library**: All core functionality uses `std` - -### Building & Testing - -```bash -# Build in debug mode -cargo build - -# Build optimized release binary -cargo build --release - -# Run tests -cargo test - -# Run with output -cargo run -- --verbose -``` - -### Test Coverage - -The parser module includes unit tests: - -```rust -#[test] -fn tokenize_basic_lets_and_pipeline() { ... } - -#[test] -fn parse_let_statement() { ... } +### Contributing -#[test] -fn parse_pipeline_with_function_block() { ... } -``` +We welcome contributions! Here's how to help: -Run tests with: -```bash -cargo test -``` +1. Fork the repo +2. Create a feature branch: git checkout -b feature/awesome-feature +3. Make your changes and write tests +4. Commit with clear messages: git commit -m "Add awesome feature" +5. Push: git push origin feature/awesome-feature +6. Open a Pull Request and describe what you did -### Contributing +--- -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/my-feature`) -3. Commit changes with clear messages -4. Add tests for new functionality -5. Push to your fork -6. Submit a pull request +## ROADMAP -### Future Enhancements +We are actively developing TruShell. Planned features: -- **Task Management API**: Commands to create, list, and complete tasks -- **Time Tracking**: `time start`, `time stop`, `time log` commands -- **Persistence**: SQLite backend for task/time storage -- **Configuration**: `.trushellrc` configuration file support -- **Scripting**: Multi-line scripts and batching -- **Shell Integration**: `.bashrc`/`.zshrc` integration for seamless use -- **Custom Functions**: User-defined functions with parameters -- **History & Completion**: Command history and tab completion +- Task Management: task create, task list, task complete +- Time Tracking: time start, time stop, time log +- Persistence: SQLite backend for tasks +- Configuration: .trushellrc config file +- Custom Functions: Define and reuse scripts +- History and Completion: Arrow keys for recall, tab completion +- Shell Integration: Load in .bashrc / .zshrc --- -## SEE ALSO +## SUPPORT + +Got questions? Ideas? Bug reports? -- **Linux Shell Documentation**: `man bash`, `man sh` -- **Rust Book**: https://doc.rust-lang.org/book/ -- **Crossterm Docs**: https://docs.rs/crossterm/ -- **Unix Philosophy**: https://en.wikipedia.org/wiki/Unix_philosophy +- Open an Issue on GitHub +- Start a Discussion if you want to chat +- Check existing issues for answers --- ## LICENSE -TruShell is released under the terms specified in `LICENSE.md`. See that file for full details. +TruShell is released under the terms in LICENSE.md. + +See LICENSE.md for full details. --- -**TruFoundation** — Empowering productivity through open-source tooling. +Made with care by TruFoundation -*Last Updated: July 5, 2026* +Empowering productivity through open-source tooling.