Skip to content

tinyopsec/tmenu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Minimal X11 menu launcher - suckless, auditable, fast.

tmenu in action

License: MIT C99 LOC Issues Stars Minimalist


tmenu reads a newline-delimited list of items from stdin, lets you filter by typing, and prints the selected entry (or the typed text, if it matches nothing) to stdout, dmenu-style. tmenu_run pipes that straight into sh, so it works as an app launcher out of the box. The whole thing fits in one C file, under 300 lines. The only runtime dependency is Xlib.


Contents


Why tmenu?

Feature tmenu dmenu rofi
Source size under 300 lines ~2500 lines ~15000 lines
Dependencies Xlib only Xlib, Xft Xlib, cairo, pango, ...
Config file none (compile-time) none (compile-time) yes
Executes typed text yes yes no
Launch overhead minimal minimal moderate
Auditable in an hour yes hard no

tmenu follows the suckless philosophy: small, auditable, compile-time configured. No config file parser, no IPC, no scripting layer. Read the source - understand the program.


Quick Start

git clone https://github.com/tinyopsec/tmenu && cd tmenu && make && sudo make install
tmenu_run

Installation

From source

git clone https://github.com/tinyopsec/tmenu
cd tmenu
make
sudo make install

Installs to /usr/local/bin/. To change the prefix:

sudo make install PREFIX=/usr

Uninstall:

sudo make uninstall

Requirements

Dependency Arch Debian
Xlib libx11 libx11-dev
C compiler gcc build-essential

AUR Arch Linux (AUR)

yay -S tmenu

macOS macOS (XQuartz)

Install XQuartz, then build from source as above.

BSD OpenBSD / FreeBSD / NetBSD

Install libX11 via ports or pkgsrc, then build from source.


Usage

Basic

# Use the bundled launcher (scans $PATH):
tmenu_run

# Pipe items manually, launcher-style:
printf "st\nfirefox\nhtop\n" | tmenu | sh

# Use it like dmenu, in a script, no execution involved:
printf "apple\nbanana\norange\n" | tmenu >> grocerylist.txt

Type to filter, navigate with arrow keys, press Enter to print the selection to stdout. If what you typed matches no item, tmenu prints the typed text instead. Piping that into sh (as tmenu_run does) is what turns it into a launcher; piping it anywhere else just gets you the selected line.

Flags

Flag Description
-b Show menu at the bottom of the screen
-l N Vertical list with N visible lines
-p text Prompt displayed left of the input field

Examples

# Vertical launcher with prompt:
printf "st\nfirefox\nthunderbird\n" | tmenu -l 5 -p "run: "

# Power menu at bottom:
printf "suspend\nreboot\npoweroff\n" | tmenu -b -p "power: "

# Session menu:
printf "lock\nlogout\n" | tmenu -b -p "session: "

Window manager integration

dwm / swm:

static const char *dmenucmd[] = { "tmenu_run", NULL };

Recompile your WM after editing the config.

i3:

bindsym $mod+d exec tmenu_run

.xinitrc example:

export PATH="$HOME/.local/bin:$PATH"
picom &
feh --bg-scale ~/wallpaper.png &
exec swm
Debugging

Check binary is available:

which tmenu
which tmenu_run

Run the launcher directly to test:

tmenu_run

If the keybinding does nothing, check:

  • $PATH is set before your WM starts (set it in .xinitrc)
  • WM config references tmenu_run correctly
  • Binary is executable: chmod +x /usr/local/bin/tmenu_run

Test with explicit input:

$ printf "echo hello\n" | tmenu

⌨ Key Bindings

Key Action
Enter / KP_Enter Execute selected item or typed text
Escape Exit without executing
BackSpace Delete character left of cursor
Up / Left Move selection up or left
Down / Right Move selection down or right
Ctrl+U Clear entire input field
Ctrl+W Delete one word left of cursor
Ctrl+K Move selection up (vertical list)
Ctrl+J Move selection down (vertical list)

To remap keys, edit the kp() function in tmenu.c and recompile.


⚙ Configuration

tmenu has no runtime config file. All settings are macros at the top of tmenu.c. Edit and recompile to apply changes:

$EDITOR tmenu.c
make && sudo make install

Compile-time settings

Macro Default Description
FONT "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*" X11 core font string
FGNORM "#bbbbbb" Normal item foreground color
BGNORM "#222222" Normal item background color
FGSEL "#eeeeee" Selected item foreground color
BGSEL "#005577" Selected item background color
TOP 1 1 = top of screen, 0 = bottom
LINES 0 Default line count (0 = horizontal)
PROMPT NULL Default prompt string

To increase limits, adjust MAXITEMS (default: 65536) and MAXTEXT (default: 256) in tmenu.c.

Example customization

-#define BGSEL   "#005577"
+#define BGSEL   "#8b0000"

-#define FONT    "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*"
+#define FONT    "-*-terminus-medium-r-*-*-14-*-*-*-*-*-*-*"

Contributing

Bug reports and patches are welcome via GitHub Issues and pull requests.

Code style

  • No comments in production code
  • No external dependencies beyond Xlib
  • No unnecessary abstraction
  • Compiles clean: gcc -std=c99 -pedantic -Wall -Wextra
  • Total source must remain under 300 lines

Features are added by patching the source, not by adding runtime options. Changes that require a config file or a new library dependency will not be accepted.


Related Projects

Project Description Link
dmenu The original dynamic menu for X suckless.org
suckless.org Philosophy behind tmenu suckless.org
Xlib manual Reference for X11 programming x.org

Star History

Star History Chart ---

License

MIT. See LICENSE for details.

About

tmenu - ultra minimal X11 menu launcher. 200 lines of C, no dependencies, compile-time config, instant focus, runs commands.

Topics

Resources

License

Stars

5 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors