Yes, I feel strongly that if dmenu_path used to keep its file in a standard
place (XDG_CACHE_HOME or as a dot in HOME), then the history should be
placed in the same location. It's just clean, uniform design.


I also realized that all the functionality of dmenu_run with history can
be kept inside one single file, removing the dependency on dmenu_path.

Basically merging dmenu_run and dmenu_path together with the history
stuff into one self-contained shell script: dmenu_run_history.

And the instructions on the wiki should simply say:

  dmenu_run_history, a self-contained alternative to dmenu_run which
  also handles history.
  
  History is saved in a file in XDG_CACHE_HOME, with fallback to a dot
  file in $HOME. Change as necessary.
  
  In addition to the above, dmenu_run_history will launch each entry
  immediately on Ctrl-Return (multiselect).

diff --git a/dmenu_run_history b/dmenu_run_history
new file mode 100755
index 0000000..6ef353d
--- /dev/null
+++ b/dmenu_run_history
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"}
+if [ -d "$cachedir" ]; then
+       cache=$cachedir/dmenu_run
+       historyfile=$cachedir/dmenu_history
+else                   # if no xdg dir, fall back to dotfiles in ~ 
+       cache=$HOME/.dmenu_cache
+       historyfile=$HOME/.dmenu_history
+fi
+
+IFS=:
+if stest -dqr -n "$cache" $PATH; then
+       stest -flx $PATH | sort -u > "$cache"
+fi
+unset IFS
+
+awk -v histfile=$historyfile '
+       BEGIN {
+               while( (getline < histfile) > 0 ) {
+                       sub("^[0-9]+\t","")
+                       print
+                       x[$0]=1
+               } 
+       } !x[$0]++ ' "$cache" \
+       | dmenu "$@" \
+       | awk -v histfile=$historyfile '
+               BEGIN {
+                       FS=OFS="\t"
+                       while ( (getline < histfile) > 0 ) {
+                               count=$1
+                               sub("^[0-9]+\t","")
+                               fname=$0
+                               history[fname]=count
+                       }
+                       close(histfile)
+               }
+
+               {
+                       history[$0]++
+                       print
+               }
+
+               END {
+                       if(!NR) exit
+                       for (f in history)
+                               print history[f],f | "sort -t '\t' -k1rn >" 
histfile
+               }
+       ' \
+       | while read cmd; do ${SHELL:-"/bin/sh"} -c "$cmd" & done

Reply via email to