Instantly share code, notes, and snippets.
Last active
July 8, 2025 05:33
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save Ajnasz/4f1586775d4c6edd3666fc376d4b3296 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
# This script extends the functionality of dmenu_run by allowing the user to | |
# include custom commands and executables. The custom commands are read from a | |
# file specified by the environment variable DMENU_RUN_COMMANDS, and the | |
# executables are read from a directory specified by the environment variable | |
# DMENU_RUN_BIN. | |
# | |
# Environment Variables: | |
# DMENU_RUN_COMMANDS: Path to a file containing custom commands to be included | |
# in the dmenu. The file should contain one command per line. | |
# Each line can be a regular command or an alias defined in the | |
# format: | |
# alias name="command --with-args" | |
# alias name="command2" | |
# | |
# DMENU_RUN_BIN: Path to a directory containing executables. | |
# The executables should echo the commands to be included in | |
# the dmenu. | |
# | |
# Usage: | |
# Set the environment variables DMENU_RUN_COMMANDS and DMENU_RUN_BIN to point | |
# to your custom commands file and executables directory, respectively. Then, | |
# run the script. The script will add the custom commands and executables to | |
# the dmenu. | |
# | |
# Example: | |
# DMENU_RUN_COMMANDS=/path/to/commands.txt DMENU_RUN_BIN=/path/to/bin \ | |
# ./dmenu_run2 | |
# | |
# Note: | |
# The script assumes that all files in the DMENU_RUN_BIN directory are | |
# executable and that they will echo the correct commands. Ensure that these | |
# conditions are met to avoid unexpected behavior. | |
# | |
# The script runs in the background, and the selected command from the dmenu | |
# is executed in a subshell. | |
# Function to extract alias name from alias definition | |
# shellcheck disable=SC2317 # Don't warn about unreachable commands in this function | |
extract_alias_name() { | |
printf '%s\n' "$1" | sed 's/^alias \([^=]*\)=.*/\1/' | |
} | |
# Function to extract alias command from alias definition | |
# shellcheck disable=SC2317 # Don't warn about unreachable commands in this function | |
extract_alias_command() { | |
printf '%s\n' "$1" | sed 's/^alias [^=]*=//' | sed 's/^"\(.*\)"$/\1/' | |
} | |
# Function to process custom commands and aliases | |
# shellcheck disable=SC2317 # Don't warn about unreachable commands in this function | |
process_custom_commands() { | |
if [ -n "$DMENU_RUN_COMMANDS" ] && [ -f "$DMENU_RUN_COMMANDS" ]; then | |
while IFS= read -r line || [ -n "$line" ]; do | |
# Skip comments and empty lines | |
case "$line" in | |
\#*|'') continue ;; | |
alias\ *=*) | |
# Extract and display alias name only | |
extract_alias_name "$line" | |
;; | |
*) | |
# Regular command | |
printf '%s\n' "$line" | |
;; | |
esac | |
done < "$DMENU_RUN_COMMANDS" | |
fi | |
} | |
# Function to resolve alias to its command | |
# shellcheck disable=SC2317 # Don't warn about unreachable commands in this function | |
resolve_alias() { | |
if [ -z "$DMENU_RUN_COMMANDS" ] || [ ! -f "$DMENU_RUN_COMMANDS" ]; then | |
# echo the stdin input to stdout | |
while IFS= read -r selected || [ -n "$selected" ]; do | |
printf '%s\n' "$selected" | |
done | |
return 0 | |
fi | |
while IFS= read -r selected || [ -n "$selected" ]; do | |
# read $DMENU_RUN_COMMANDS and resolve aliases | |
while IFS= read -r line || [ -n "$line" ]; do | |
case "$line" in | |
alias\ *=*) | |
alias_name=$(extract_alias_name "$line") | |
if [ "$selected" = "$alias_name" ]; then | |
alias_command=$(extract_alias_command "$line") | |
# If selected item is an alias, print its command | |
printf '%s\n' "$alias_command" | |
return 0 | |
fi | |
;; | |
*) | |
# If selected item is a regular command, print it as is | |
if [ "$selected" = "$line" ]; then | |
printf '%s\n' "$line" | |
return 0 | |
fi | |
;; | |
esac | |
done < "$DMENU_RUN_COMMANDS" | |
printf '%s\n' "$selected" | |
done | |
} | |
if [ -z "$DMENU_RUN_BIN" ] || [ ! -d "$DMENU_RUN_BIN" ];then | |
echo "DMENU_RUN_BIN is not set or is not a directory" >&2 | |
fi | |
if [ -z "$DMENU_RUN_COMMANDS" ] || [ ! -f "$DMENU_RUN_COMMANDS" ];then | |
echo "DMENU_RUN_COMMANDS is not set or is not a file" >&2 | |
fi | |
DMENU="dmenu" | |
# DMENU="rofi -dmenu -i -no-fixed-num-lines -no-show-icons" | |
if [ -n "$WAYLAND_DISPLAY" ]; then | |
DMENU="bemenu" | |
fi | |
{ | |
# include output of executables from DMENU_RUN_BIN | |
if [ -n "$DMENU_RUN_BIN" ] && [ -d "$DMENU_RUN_BIN" ]; then | |
find "$DMENU_RUN_BIN" -maxdepth 1 -type f -executable -exec {} \; | |
fi | |
# include custom commands from DMENU_RUN_COMMANDS | |
if [ -n "$DMENU_RUN_COMMANDS" ] && [ -f "$DMENU_RUN_COMMANDS" ]; then | |
process_custom_commands < "$DMENU_RUN_COMMANDS" | |
fi | |
# always include dmenu_path | |
if [ "$DMENU_NO_PATH" != "true" ]; then | |
dmenu_path; | |
fi | |
} | $DMENU "$@" | resolve_alias | env FZF="$DMENU $*" "${SHELL:-"/usr/bin/env sh"}" & | |
exit 0; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment