openbsd-dotfiles

Base configurations for my Openbsd desktop
git clone https://git.kausban.com/openbsd-dotfiles/raw/.git
Log | Files | Refs

dmenu-recent (2216B)


      1 #!/bin/sh
      2 set -eu
      3 
      4 DMENU_CMD="dmenu -i -p > -fn monospace:size=12 -nb #222222 -nf #bbbbbb -sb #005577 -sf #eeeeee"
      5 TERMINAL="st -e"
      6 MAX_RECENT=199 # Number of recent commands to track
      7 
      8 CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/dmenu-recent"
      9 RECENT_CACHE="$CACHE_DIR/recent"
     10 REST_CACHE="$CACHE_DIR/all"
     11 KNOWN_TYPES=" background terminal terminal_hold "  # end spaces needed for case match in get_types
     12 
     13 CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/dmenu-recent"
     14 mkdir -p "$CACHE_DIR"
     15 mkdir -p "$CONFIG_DIR"
     16 touch "$RECENT_CACHE"
     17 
     18 IFS=:
     19 if stest -dqr -n "$REST_CACHE" $PATH 2>/dev/null; then
     20     stest -flx $PATH | sort -u | grep -vf "$RECENT_CACHE" > "$REST_CACHE"
     21 fi
     22 
     23 IFS=' '
     24 CMD=$(cat "$RECENT_CACHE" "$REST_CACHE" | $DMENU_CMD) || exit
     25 
     26 # Sanitize the input
     27 CMD_NAME=$(printf "%s" "$CMD" | cut -f1 -d' ')  # Extract the command name
     28 if ! command -v "$CMD_NAME" >/dev/null 2>&1; then
     29     echo "Invalid command: $CMD_NAME" >&2
     30     exit 1
     31 fi
     32 
     33 # Ensure input doesn't contain unwanted symbols
     34 if printf "%s" "$CMD" | grep -q '[!$`(){};&|\*?<>]'; then
     35     echo "Invalid characters in command: $CMD" >&2
     36     exit 1
     37 fi
     38 
     39 if ! grep -qx "$CMD" "$RECENT_CACHE" >/dev/null 2>&1; then
     40     grep -vx "$CMD" "$REST_CACHE" > "$REST_CACHE.$$"
     41     mv "$REST_CACHE.$$" "$REST_CACHE"
     42 fi
     43 
     44 echo "$CMD" > "$RECENT_CACHE.$$"
     45 grep -vx "$CMD" "$RECENT_CACHE" | head -n "$MAX_RECENT" >> "$RECENT_CACHE.$$"
     46 mv "$RECENT_CACHE.$$"  "$RECENT_CACHE"
     47 
     48 WORD0=${CMD%% *}
     49 
     50 MATCH="^$WORD0$"
     51 
     52 get_type () {
     53 	TYPE=""
     54     while TYPE=$(echo "$KNOWN_TYPES" | xargs -n1 | $DMENU_CMD -p 'Type:'); do
     55 		case " $KNOWN_TYPES " in
     56 			*" $TYPE "*) ;;
     57 			*) continue ;;
     58 		esac
     59         echo "$WORD0" >> "$CONFIG_DIR/$TYPE"
     60         break
     61     done
     62     echo $TYPE
     63 }
     64 
     65 TYPE=$(grep -lx "$MATCH" -R "$CONFIG_DIR" 2>/dev/null || true)
     66 
     67 if [ -z "$TYPE" ]; then
     68     TYPE=$(get_type)
     69 else
     70     TYPE=$(basename "$TYPE")
     71     if ! echo "$KNOWN_TYPES" | grep -q " $TYPE "; then
     72         rm -f "$CONFIG_DIR/$TYPE"
     73         TYPE=$(get_type)
     74     fi
     75 fi
     76 
     77 case "$TYPE" in
     78     background)
     79         exec $CMD
     80         ;;
     81     terminal)
     82         exec $TERMINAL "$CMD"
     83         ;;
     84     terminal_hold)
     85         exec $TERMINAL sh -c "$CMD && echo 'Press Enter to kill me...' && read _"
     86         ;;
     87 esac