alexrios/zmenu
A cross-platform dmenu-like application launcher built with Zig and SDL3.
masterA cross-platform dmenu-like application launcher built with Zig and SDL3.
zmenu reads items from stdin and displays them in a menu:
# Simple example
echo -e "Apple\nBanana\nCherry\nDate\nEldberry" | zmenu
# From a file
cat items.txt | zmenu
# Use with find
find . -type f | zmenu
The selected item is written to stdout, making it easy to use in scripts:
selected=$(find ~/projects -maxdepth 1 -type d | zmenu)
cd "$selected"
Navigation:
↑ / k - Move selection up↓ / j - Move selection downTab - Move to next itemShift+Tab - Move to previous itemPage Up - Jump up one page (10 items)Page Down - Jump down one page (10 items)Home - Jump to first itemEnd - Jump to last itemInput:
Backspace - Delete last character (UTF-8 aware)Ctrl+U - Clear entire inputCtrl+W - Delete last wordActions:
Enter - Select current item and output to stdoutEscape / Ctrl+C - Cancel without selection> prefix and highlighted colorzmenu supports multiple color themes via the ZMENU_THEME environment variable:
# Use a specific theme (note: env var must be set for zmenu, not the input command)
echo -e "Apple\nBanana\nCherry" | ZMENU_THEME=dracula zmenu
# Works with any command
find . -type f | ZMENU_THEME=nord zmenu
# Or export first, then use normally
export ZMENU_THEME=gruvbox
seq 1 100 | zmenu
# Set as default in your shell config (~/.bashrc, ~/.zshrc, etc.)
export ZMENU_THEME=gruvbox
Catppuccin Family (pastel themes):
Classic Themes:
If ZMENU_THEME is not set or contains an invalid name, zmenu defaults to mocha.
Theme names are case-insensitive (NORD, nord, and NoRd all work).
curl https://mise.run | sh
mise install
mise run build
mise run build - Build the projectmise run run - Run the applicationmise run test - Run testsmise run clean - Clean build artifactsmise run check - Check code without buildingzmenu/
├── .mise.toml # Mise configuration and tasks
├── build.zig # Build configuration
├── build.zig.zon # Dependencies (zig-sdl3)
├── src/
│ ├── main.zig # Main application (~740 lines)
│ └── theme.zig # Theme definitions (8 color themes)
└── README.md
The fuzzy matcher allows characters to appear in order but not necessarily consecutively:
Query: "abc"
Matches: "AaBbCc", "a_long_b_string_c", "AbsolutelyBigCat"
No Match: "cba", "acb"
Important: Case-insensitive matching only works for ASCII characters (a-z, A-Z). UTF-8 characters like é, ü, 日 are matched byte-for-byte:
This design choice ensures UTF-8 safety without complex Unicode normalization.
This project follows a pragmatic approach:
The project includes automated tests covering critical functionality:
mise run test # Run all tests
Test Coverage:
All tests use Zig's built-in testing framework and run on every build.
Supported Platforms: Linux, macOS, Windows
Building for different platforms:
# Native build
mise run build
# Cross-compile to Windows
zig build -Dtarget=x86_64-windows
# Cross-compile to macOS
zig build -Dtarget=x86_64-macos
# Cross-compile to Linux
zig build -Dtarget=x86_64-linux
Planned:
Configuration file support (~/.config/zmenu/config.toml)
History tracking with frecency scoring
Multi-column layout option
Preview pane for file paths
Custom keybinding support
Maybe:
Plugin system for custom filters
Custom theme support (user-defined colors)
Desktop file integration (.desktop files)
Icon support
This is a learning project exploring Zig + SDL3.
Discussions, issues and PRs are welcomed!
This project is open source. Use it however you'd like.