prmt π
Ultra-fast, customizable shell prompt generator written in Rust. Features zero-copy parsing with SIMD optimizations for sub-microsecond template processing.
Features
- β‘ Blazing Fast: Sub-microsecond parsing with memchr SIMD optimizations
- π§ Modular Architecture: Clean separation with Module trait and registry system
- π¨ Rich Template Language: 5-field format with styles, formats, and affixes
- π¦ Zero-Copy Parsing: 50-70% reduction in allocations
- π¦ Memory Efficient: Single-pass parser with lazy unescaping
- π Parallel Detection: Module detection runs concurrently via Rayon
- π₯ Gitoxide Integration: 2.9x faster git operations
- β¨ Smart Rendering: Conditional display based on context
Performance
Parser Performance (Template Processing)
| Template Type | Performance | Improvement |
|---|---|---|
Simple {path} |
~0.2 Β΅s | 3.7x faster |
| Complex (5 modules + styles) | ~1.1 Β΅s | 4.7x faster |
| Long text (100+ chars) | ~0.1 Β΅s | 7.6x faster |
| Many placeholders | ~2.0 Β΅s | 3.8x faster |
End-to-End Performance
| Scenario | Time | Notes |
|---|---|---|
| Path only | ~0.01ms | Minimal prompt |
| Path + Git | ~1-2ms | Branch and status |
| With Rust version | ~25-30ms | Includes rustc --version |
With --no-version |
<5ms | Skips all version detection |
Key Optimizations
Parser (NEW):
- Zero-copy parsing - Text sections are slices, not allocations
- SIMD scanning - memchr finds
{,},\in parallel - Lazy unescaping - Only allocates for fields with backslashes
- Single-pass - No backtracking or re-parsing
Runtime:
- Gitoxide (gix) - 2.9x faster than git2 for git operations
- Parallel detection - All modules detected simultaneously via Rayon
- Direct execution - No compilation or caching overhead
- Conditional rendering - Modules only render when conditions met
Installation
# Build from source (Rust 2024 edition required)
# Or install directly
# Verify installation
Format Specification
Format Syntax
{module} - Default everything
{module:style} - Custom style
{module:style:type} - Custom style and type
{module:style:type:prefix} - Add prefix to value
{module:style:type:prefix:postfix} - Add prefix and postfix
# Omitting parts (empty means default)
{module::::suffix} - Default style/type, suffix only
{module:::prefix:} - Default style/type, prefix only
{module:::prefix:suffix} - Default style/type, both prefix/suffix
{module::type} - No style, specific type
{module::type::suffix} - No style, specific type, suffix only
Available Modules
| Module | Detection | Description |
|---|---|---|
path |
Always active | Current directory with ~ for home |
ok |
Exit code = 0 | Shows when last command succeeded (default: β―) |
fail |
Exit code β 0 | Shows when last command failed (default: β―) |
git |
.git directory |
Branch name with status indicators |
node |
package.json |
Node.js version |
python |
requirements.txt, pyproject.toml, etc |
Python version |
rust |
Cargo.toml |
Rust version |
deno |
deno.json, deno.jsonc |
Deno version |
bun |
bun.lockb |
Bun version |
go |
go.mod |
Go version |
Type Values
Version modules (rust, node, python, etc.):
fullorf- Full version (1.89.0)shortors- Major.minor (1.89)majororm- Major only (1)
Path module:
relativeorr- Path with ~ for home directory (default)absoluteora- Full absolute path without ~ substitutionshortors- Last directory only
Git module:
fullorf- Branch with status (default)shortors- Branch name only
Ok/Fail modules:
full- Default symbol (β―)code- Shows the actual exit code number- Any other string - Uses that string as the symbol (e.g.,
{ok::β}shows β)
Type Validation
The format parser validates types at parse time to catch errors early:
# Valid types for each module
# Invalid types produce clear errors
# Error: Invalid type 'major' for module 'path'. Valid types: relative, r, absolute, a, short, s
# Error: Invalid type 'major' for module 'git'. Valid types: full, short
Default Module Styles
| Module | Default Color | Can Override |
|---|---|---|
path |
cyan | Yes |
ok |
green | Yes |
fail |
red | Yes |
git |
purple | Yes |
node |
green | Yes |
rust |
red | Yes |
python |
yellow | Yes |
go |
cyan | Yes |
deno |
- | Yes |
bun |
- | Yes |
Styles
Colors: black, red, green, yellow, blue, purple, cyan, white, #hexcode
Modifiers: bold, dim, italic, underline, reverse, strikethrough
Combine with dots: cyan.bold, red.dim.italic
Escaping
\{β{(literal brace)\}β}(literal brace)\nβ newline\tβ tab\:β:(literal colon in fields)\\β\(literal backslash)
Usage Examples
# Simple format with defaults
# Output: ~/projects 1.89.0 master
# Format with types and styles
# Simplified formats with omitted parts
# Add your own icons with prefix
# Using short format aliases
# No style with type
# With exit code indicators (requires --code flag)
# Output (success): ~/projects β― (green)
# Output (failure): ~/projects β― (red)
# Fast mode (no version detection)
# Output: ~/projects (only shows active modules, no versions)
# Custom symbols for ok/fail using type as symbol
# Output (success): ~/projects β
# Output (failure): ~/projects β
# Show exit code on failure
# Output (success): ~/projects β―
# Output (failure with code 127): ~/projects 127
Shell Integration
Bash
# Add to ~/.bashrc
PS1='$(prmt --code $? "{path:cyan:s} {git:purple:s:on :} {ok:green}{fail:red}")\$ '
# Or set via environment variable
PS1='$(prmt --code $?)\$ '
Zsh
# Add to ~/.zshrc
PROMPT='$(prmt --code $? "{path:cyan:s} {git:purple:s:on :} {ok:green}{fail:red}") '
# Or with environment variable
PROMPT='$(prmt --code $?) '
Fish
# Add to ~/.config/fish/config.fish
function fish_prompt
prmt --code $status '{path:cyan:s} {git:purple:s:on :} {ok:green}{fail:red} '
end
# Or with environment variable
set -x PRMT_FORMAT "{path:cyan:r} {python:yellow:m:π :} {git:purple}"
function fish_prompt
prmt --code $status
end
PowerShell
# Add to $PROFILE
function prompt {
prmt --code $LASTEXITCODE '{path:cyan:s} {git:purple:s:on :} {ok:green}{fail:red} '
}
# Or with environment variable
$env:PRMT_FORMAT = "{path:cyan:r} {git:purple}"
function prompt {
prmt --code $LASTEXITCODE
}
Command-Line Options
prmt [OPTIONS] [FORMAT]
OPTIONS:
-n, --no-version Skip version detection for speed
-d, --debug Show debug information and timing
-b, --bench Run benchmark (100 iterations)
--code <CODE> Exit code of the last command (for ok/fail modules)
-h, --help Print help
-V, --version Print version
ARGS:
<FORMAT> Format string (default from PRMT_FORMAT env var)
Architecture
Clean Modular Design
βββββββββββββββ ββββββββββββ βββββββββββ
β Parser ββββββΆβ Tokens ββββββΆβ Executorβ
β (memchr) β β β β β
βββββββββββββββ ββββββββββββ ββββββ¬βββββ
β
βββββββββββββββββββββββΌβββββββββββββββ
β Module Registry β
β ββββββββ ββββββββ ββββββββ β
β β Path β β Git β β Rust β ... β
β ββββββββ ββββββββ ββββββββ β
ββββββββββββββββββββββββββββββββββββββ
Execution Pipeline
- Parse - Single-pass, zero-copy template parsing (~1Β΅s)
- Registry Lookup - O(1) module resolution via HashMap
- Render - Modules validate and render in parallel
- Style - ANSI styling applied as final step
Module System
All modules implement a simple trait:
- Return
Some(text)to display - Return
Noneto hide (inactive/error) - Validation happens during render (lazy)
Parser Implementation
- memchr3 for SIMD scanning of
{,},\ - Zero-copy text slices for literal sections
- Lazy unescaping with
Cow<str>for efficiency - Single allocation for final output string
Building from Source
# Requirements: Rust 2024 edition
# Run tests
# Benchmark
License
MIT