343 lines
8.6 KiB
Markdown
343 lines
8.6 KiB
Markdown
# Luash - Minimal Lua Shell Scripting
|
|
|
|
A lightweight Lua preprocessor that makes Lua a capable shell scripting language, combining the readability of Lua with the power of shell commands.
|
|
|
|
## Why Luash?
|
|
|
|
**Clean Syntax**: No more `$((arithmetic))`, `${parameter:-default}`, or complex quoting nightmares
|
|
**Real Programming**: Full Lua language features - tables, functions, proper data structures
|
|
**Shell Integration**: Seamless shell command execution with familiar syntax
|
|
**Minimal**: Just 4 core functions, no bloat
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
#!/usr/bin/env luash
|
|
|
|
# Environment variables (clean syntax)
|
|
print("Hello " .. $USER .. "!")
|
|
|
|
# Variable assignment
|
|
$MY_VAR = "some value"
|
|
|
|
# Shell commands with backticks
|
|
files = `ls -la`
|
|
current_dir = `pwd`
|
|
|
|
# Interactive commands
|
|
!git status
|
|
|
|
# The power of Lua + shell
|
|
if `test -f README.md` ~= "" then
|
|
lines = `wc -l < README.md`
|
|
print("README has " .. lines .. " lines")
|
|
end
|
|
```
|
|
|
|
## Core Features
|
|
|
|
### Environment Variables
|
|
```lua
|
|
# Access with clean $ syntax
|
|
print("User: " .. $USER)
|
|
print("Shell: " .. $SHELL)
|
|
|
|
# Assignment
|
|
$MY_VAR = "hello world"
|
|
print($MY_VAR)
|
|
|
|
# Inside strings are preserved literally
|
|
print("This prints: $USER (not substituted)")
|
|
```
|
|
|
|
### Shell Commands
|
|
```lua
|
|
# Command substitution with backticks
|
|
files = `ls -la`
|
|
date = `date +%Y-%m-%d`
|
|
|
|
# Variable interpolation in commands
|
|
service = "ssh"
|
|
result = `pgrep #{service} | wc -l`
|
|
|
|
host = "google.com"
|
|
ping_result = `ping -c 1 #{host} >/dev/null 2>&1 && echo "ok"`
|
|
|
|
# Interactive commands (direct output)
|
|
!git status
|
|
!top
|
|
```
|
|
|
|
### The Power of Lua
|
|
```lua
|
|
# Real data structures
|
|
users = {"alice", "bob", "charlie"}
|
|
for i = 1, #users do
|
|
print("User " .. i .. ": " .. users[i])
|
|
end
|
|
|
|
# Functions and logic
|
|
function backup_file(filename)
|
|
if `test -f ` .. filename .. `` ~= "" then
|
|
`cp ` .. filename .. ` ` .. filename .. `.bak`
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
```
|
|
|
|
## 🎯 Examples
|
|
|
|
Explore organized examples that demonstrate Luash features:
|
|
|
|
```bash
|
|
# Start with the showcase for a complete overview
|
|
./luash examples/09_showcase.luash
|
|
|
|
# Learn step-by-step with numbered examples
|
|
./luash examples/01_basic_features.luash
|
|
./luash examples/02_quick_comparison.luash
|
|
./luash examples/03_interpolation.luash
|
|
|
|
# Try practical use cases
|
|
./luash examples/04_system_admin.luash
|
|
./luash examples/05_development.luash
|
|
./luash examples/06_data_processing.luash
|
|
|
|
# Or use the interactive runner
|
|
./luash run_examples.luash
|
|
```
|
|
|
|
See [examples/README.md](examples/README.md) for the complete learning path.
|
|
|
|
### What You Get
|
|
|
|
#### File System Operations
|
|
```lua
|
|
-- Check file existence
|
|
if fs.exists("config.txt") then
|
|
content = fs.read("config.txt")
|
|
end
|
|
|
|
-- File operations
|
|
fs.write("output.txt", "Hello World")
|
|
fs.append("log.txt", "New entry\n")
|
|
|
|
-- Advanced file operations
|
|
file.copy("source.txt", "backup.txt")
|
|
file.move("old.txt", "new.txt")
|
|
lines = file.lines("data.txt") -- Read as array of lines
|
|
```
|
|
|
|
#### Directory Operations
|
|
```lua
|
|
-- Directory management
|
|
dir.create("new_folder") -- mkdir -p equivalent
|
|
files = dir.list("/tmp") -- List directory contents
|
|
current = dir.pwd() -- Get current directory
|
|
|
|
-- Convenience aliases
|
|
mkdir("test")
|
|
cd("/home/user")
|
|
ls("/var/log")
|
|
```
|
|
|
|
#### String Utilities
|
|
```lua
|
|
-- String manipulation
|
|
parts = str.split("a,b,c", ",")
|
|
clean = str.trim(" whitespace ")
|
|
bool = str.starts_with("hello", "hel")
|
|
|
|
-- Text processing
|
|
result = text.grep("pattern", "file.txt")
|
|
lines = text.head(10, "large_file.txt")
|
|
count = text.wc("-l", "data.txt") -- Line count
|
|
```
|
|
|
|
#### Array/Table Operations
|
|
```lua
|
|
-- Array utilities
|
|
found = array.contains({"a", "b", "c"}, "b")
|
|
doubled = array.map({1, 2, 3}, function(x) return x * 2 end)
|
|
evens = array.filter({1, 2, 3, 4}, function(x) return x % 2 == 0 end)
|
|
```
|
|
|
|
#### Path Utilities
|
|
```lua
|
|
-- Path manipulation
|
|
full_path = path.join("/usr", "local", "bin", "luash")
|
|
dir_name = path.dirname("/path/to/file.txt") -- "/path/to"
|
|
base_name = path.basename("/path/to/file.txt") -- "file.txt"
|
|
extension = path.ext("document.pdf") -- "pdf"
|
|
```
|
|
|
|
#### System Information
|
|
```lua
|
|
-- System utilities
|
|
os_name = sys.os() -- "linux", "darwin", etc.
|
|
arch = sys.arch() -- "x86_64", "arm64", etc.
|
|
hostname = sys.hostname() -- Get machine name
|
|
user = sys.whoami() -- Current username
|
|
memory_info = sys.memory() -- Memory usage
|
|
disk_info = sys.disk("/") -- Disk usage
|
|
```
|
|
|
|
#### Network Operations
|
|
```lua
|
|
-- Network utilities
|
|
success = net.download("https://example.com/file.txt", "local_file.txt")
|
|
response = net.get("https://api.example.com/data")
|
|
post_result = net.post("https://api.example.com/submit", "key=value")
|
|
reachable = net.ping("google.com", 3) -- Ping 3 times
|
|
```
|
|
|
|
#### Process Management
|
|
```lua
|
|
-- Process operations
|
|
my_pid = proc.pid()
|
|
git_path = proc.which("git") -- Find executable path
|
|
|
|
-- Job control
|
|
job.background("long_running_command")
|
|
job.kill(1234, "TERM") -- Kill process by PID
|
|
job.killall("firefox") -- Kill all processes by name
|
|
processes = job.ps() -- Get process list
|
|
```
|
|
|
|
#### Logging and Colors
|
|
```lua
|
|
-- Colored logging
|
|
log.info("Information message")
|
|
log.warn("Warning message")
|
|
log.error("Error message")
|
|
log.success("Success message")
|
|
|
|
-- Color output
|
|
print(color.red("Error text"))
|
|
print(color.green("Success text"))
|
|
print(color.bold(color.yellow("Important notice")))
|
|
```
|
|
|
|
#### Archive Operations
|
|
```lua
|
|
-- Compression utilities
|
|
archive.tar_create("backup.tar.gz", {"file1.txt", "file2.txt"})
|
|
archive.tar_extract("backup.tar.gz", "/destination")
|
|
archive.zip_create("archive.zip", {"folder1", "folder2"})
|
|
archive.zip_extract("archive.zip", "/extract_here")
|
|
```
|
|
|
|
### Convenience Aliases
|
|
|
|
Common shell commands are available as Lua functions:
|
|
|
|
```lua
|
|
ls() -- ls -la
|
|
pwd() -- Get current directory
|
|
cd("/path") -- Change directory
|
|
mkdir("folder") -- Create directory
|
|
rm("file") -- Remove file
|
|
cp("src", "dst") -- Copy file
|
|
mv("old", "new") -- Move/rename file
|
|
cat("file.txt") -- Read file contents
|
|
echo("Hello") -- Print and return text
|
|
grep("pattern", "file.txt") -- Search in file
|
|
head(5, "file.txt") -- First 5 lines
|
|
tail(10, "file.txt") -- Last 10 lines
|
|
wc("-l", "file.txt") -- Count lines
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Basic Usage
|
|
```bash
|
|
./luash script.luash
|
|
```
|
|
|
|
### Interactive Shell (REPL)
|
|
```bash
|
|
./luash -i
|
|
# or
|
|
./luash --interactive
|
|
```
|
|
|
|
The interactive shell supports:
|
|
- All luash preprocessing features
|
|
- Multiline input for functions, loops, etc.
|
|
- Command history with `.history`
|
|
- Screen clearing with `.clear`
|
|
- Special commands: `.help`, `.exit`, `.clear`
|
|
- Real-time expression evaluation
|
|
|
|
See [examples/08_repl_guide.luash](examples/08_repl_guide.luash) for a comprehensive guide.
|
|
|
|
### Debug Mode
|
|
```bash
|
|
LUASH_DEBUG=1 ./luash script.luash
|
|
```
|
|
|
|
## Installation
|
|
|
|
1. Clone or download the luash repository
|
|
2. Make the script executable: `chmod +x luash`
|
|
3. Optionally, add to your PATH for system-wide access
|
|
|
|
## Syntax Examples
|
|
|
|
### Environment Variables in Strings
|
|
```lua
|
|
-- These will substitute environment variables
|
|
message = "Hello ${USER}, your shell is ${SHELL}"
|
|
path = "$HOME/Documents"
|
|
|
|
-- These will print literally (inside double quotes)
|
|
print("This will just print normally $SHELL")
|
|
print("This will substitute with the environment variable ${SHELL}")
|
|
```
|
|
|
|
### Command Interpolation
|
|
```lua
|
|
-- Variable substitution in commands
|
|
branch = "main"
|
|
result = `git checkout #{branch}`
|
|
|
|
-- Multiple variables
|
|
user = "john"
|
|
host = "server.com"
|
|
output = `ssh #{user}@#{host} 'ls -la'`
|
|
```
|
|
|
|
### File Processing Pipeline
|
|
```lua
|
|
-- Read, process, and write files
|
|
lines = file.lines("input.txt")
|
|
processed = array.map(lines, function(line)
|
|
return str.trim(line):upper()
|
|
end)
|
|
file.write_lines("output.txt", processed)
|
|
```
|
|
|
|
## Why Luash?
|
|
|
|
- **Readable**: Lua's clean syntax is more maintainable than bash
|
|
- **Powerful**: Full programming language features (tables, functions, modules)
|
|
- **Fast**: Lua is lightweight and executes quickly
|
|
- **Portable**: Works on any system with Lua installed
|
|
- **Safe**: Better error handling than shell scripts
|
|
- **Familiar**: Shell-like utilities with programming language benefits
|
|
|
|
## Preprocessor Pipeline
|
|
|
|
Luash applies several preprocessing steps:
|
|
|
|
1. **Environment Variable Substitution**: `$VAR` and `${VAR}` → `env.get('VAR')`
|
|
2. **Interactive Command Processing**: `!command` → `run('command')`
|
|
3. **Shell Command Substitution**: `` `command` `` → `shell('command')`
|
|
4. **Variable Interpolation**: `#{var}` in commands → Lua string concatenation
|
|
5. **Library Injection**: Comprehensive shell utilities loaded automatically
|
|
|
|
## License
|
|
|
|
This project is designed to make shell scripting more pleasant and maintainable while retaining the power and familiarity of traditional shell tools.
|