You are not logged in.

#301 2015-11-14 10:07:02

Yggdrasil
Member
Registered: 2009-07-21
Posts: 37

Re: Dmenu Hacking Thread

I don't know what dmenu script you are refering to, but in general: The dmenu program gets restarted and the window reopened. This might flicker.

Offline

#302 2015-11-14 12:43:51

nbd
Member
Registered: 2014-08-04
Posts: 389

Re: Dmenu Hacking Thread

Yggdrasil wrote:

The dmenu program gets restarted and the window reopened.

Between the old menu closes and new menu opens there is a time delay maybe 0.3 or 0.5 seconds, so it's rather constant popping up than tiny flickering. The script is the following:

https://bbs.archlinux.org/viewtopic.php … 7#p1577607

I guess that calling the 'ls' and 'echo' contributes to this time delay, but maybe some refactoring of program logic can be done so that directory listing could be  performed while either the old or new menu are on the screen. That's the first time I work with dmenu scripting, so maybe I don't know some common tricks in script optimizations.


bing different

Offline

#303 2015-11-24 12:44:24

Yggdrasil
Member
Registered: 2009-07-21
Posts: 37

Re: Dmenu Hacking Thread

orshiro made a script collection once which contains two similar scripts: dmenu_fm and dmenu_fmenu

https://github.com/orschiro/dmenu-scripts-collection

You might find some inspirations there. Otherwise i can't really help you. I'm not using dmenu for this kind of stuff.

Offline

#304 2015-11-24 13:12:28

nbd
Member
Registered: 2014-08-04
Posts: 389

Re: Dmenu Hacking Thread

Thanks, that link is great. But the original question actually was  "Is such delay between menu transitions normal?". If someone uses dmenu for listing directories, do they observe the delays in transitions between  menu windows or the new menu replaces the old one almost instantly? If such delays is not a normal phenomenon, then one could look how to fine tune the script to optimize them out. ( Since dmenu is written in C and very lightweight the delays must be caused in somewhere else. )


bing different

Offline

#305 2015-11-24 14:22:15

Yggdrasil
Member
Registered: 2009-07-21
Posts: 37

Re: Dmenu Hacking Thread

Make a short screencast with ffmpeg or so. Otherwise it's hard to tell what you consider an annoying delay. When i run your script, it flickers between folders, but it's short enough that i wouldn't care.

Offline

#306 2015-11-24 15:48:09

nbd
Member
Registered: 2014-08-04
Posts: 389

Re: Dmenu Hacking Thread

sleep 0.5; echo Menu

If this line to run in terminal, then the time between pressing Enter and appearing the 'Menu' string shows exactly the delay that I'm talking about. If you see only negligible flickering with the 'Dmen File Manager' script, then I probably should try to tweak some settings somewhere.


bing different

Offline

#307 2015-11-25 11:01:34

Yggdrasil
Member
Registered: 2009-07-21
Posts: 37

Re: Dmenu Hacking Thread

It's much faster for me. More like a blink of an eye.

Offline

#308 2015-11-25 15:52:02

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: Dmenu Hacking Thread

This is a hacking, not a support, thread.


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#309 2015-11-25 16:40:34

Rasi
Member
From: Germany
Registered: 2007-08-14
Posts: 1,914
Website

Re: Dmenu Hacking Thread

In short: its not possible. dmenu needs to be restarted to receive new input from stdin. it's a one-shot procedure. No way around it.


He hoped and prayed that there wasn't an afterlife. Then he realized there was a contradiction involved here and merely hoped that there wasn't an afterlife.

Douglas Adams

Offline

#310 2016-05-11 17:46:19

Z2h-A6n
Member
Registered: 2014-08-06
Posts: 7

Re: Dmenu Hacking Thread

I made a dmenu interface to remind, which I use to manage my calendar and reminders. It's basically a series of nested menus for editing and displaying parts of the calendar. It requires remind and notify-send (for displaying the calendar).

Here's the code:

#!/bin/bash

# Uses dmenu and notify-send to edit and display reminders with remind.
# Usage:
# 	remindMenu.sh  [--dir directory] [dmenu options]
#
# 	The --dir option tells the script where to look for your reminder files. This must be the first option Default: $HOME
# 	All other options are passed directly to each instance of dmenu.
# 
# Bugs/Features:
# 	* Editing and deleting operations only act on single lines

# Configuration variables
colWidth=180    # Text width (# of characters) for remind output
actions=( "List events" "Add event" "Edit event" "Delete event" )   # Array of possible actions
remDir=$HOME

# Parse optional directory argument
if [[ $1 == "--dir" ]]; then
	remDir=$2
	shift 2
fi

# Read all remaining arguments to pass them to dmenu
for i in "$@"; do
	DMENU_ARGS="$DMENU_ARGS$i "
done

# Prompt for action
action="$( printf "%s\n" "${actions[@]}" | dmenu -p 'Choose an action: ' $DMENU_ARGS )"

case $action in
	"${actions[0]}") # List
		lRange="$( dmenu -p 'Which events?: ' <<< $'Today\nThis Week\nNext 4 Weeks\nThis Month' $DMENU_ARGS )"
		case $lRange in
			'Today') # List today's events
				summary="Today:\n"
				output="$( remind "$remDir/main.rem" | tail -n+3 | sed -e 's/today //g' )"
				if [ -z "$output" ]; then
					summary="No events today."
				fi
				;;
			'This Week') # List this week's events
				summary="This week:\n"
				output="$( remind -w$colWidth -c+1 "$remDir/main.rem" )"
				;;
			'Next 4 Weeks') # List events in the next 4 weeks
				summary="Next 4 weeks:\n"
				output="$( remind -w$colWidth -c+4 "$remDir/main.rem" )"
				;;
			'This Month') # List events in the current month
				summary=" "
				output="$( remind -w$colWidth -c "$remDir/main.rem" )"
				;;
			*) # Catchall -- exit
				;;
		esac
		notify-send -u low "$summary" "$output"
		;;
	"${actions[1]}") # Add
		# Select reminder file
		while [ ! -f $remDir ]; do
			remDir="$remDir/$( ls -aC1 "$remDir" | dmenu -p 'Reminder file: ' $DMENU_ARGS )"
		done

		# Get event trigger
		DATE="$(date +%Y-%m-%d)"
		TIME="$(date +%R)"
		trigger="$( dmenu -l 2 -p 'Event trigger: ' <<< "REM $DATE +0 *0 UNTIL $DATE AT $TIME +0 *0" $DMENU_ARGS )"

		# Get event body
		body="$( dmenu -p 'Event body: ' <<< $'MSG %" %" %b %2' $DMENU_ARGS )"

		# Confirm reminder entry
		confirm='N'
		confirm="$( dmenu -p "$trigger $body | Write to ${remDir##*/} ?" $DMENU_ARGS <<< $'y\nN' )"

		# Write reminder to reminder file
		if [ "${confirm,,}" = "y" ]; then
			echo "$trigger $body" >> $remDir
			# Actually write the file
		fi
		;;
	"${actions[2]}") # Edit
		# Select reminder file
		while [ ! -f $remDir ]; do
			remDir="$remDir/$( ls -aC1 "$remDir" | dmenu -p 'Reminder file: ' $DMENU_ARGS )"
		done

		# Select reminder entry (Only selects a single line)
		oldEvent="$( cat "$remDir" | dmenu -l $( cat "$remDir" | wc -l ) -p 'Select an event:' $DMENU_ARGS )"

		# Edit line
		newEvent="$( dmenu -l 2 -p 'New event:' $DMENU_ARGS <<< "$oldEvent" )"

		# Confirm edit
		confirm='N'
		confirm="$( dmenu -p "$newEvent | Write to ${remDir##*/} ?" $DMENU_ARGS <<< $'y\nN' )"

		# Overwrite reminder to reminder file
		if [ "${confirm,,}" = "y" ]; then
			sedNew="$( sed -e 's/[\/&]/\\&/g' <<< $newEvent )"
			sedOld="$( sed -e 's/[]\/$*.^.^|[]/\\&/g' <<< $oldEvent )"
			sed -i 's/'"$sedOld"'/'"$sedNew"'/g' "$remDir"
		fi
		;;
	"${actions[3]}") # Delete
		# Select reminder file
		while [ ! -f $remDir ]; do
			remDir="$remDir/$( ls -aC1 "$remDir" | dmenu -p 'Reminder file: ' $DMENU_ARGS )"
		done

		# Select reminder entry (Only selects a single line)
		oldEvent="$( cat "$remDir" | dmenu -l $( cat "$remDir" | wc -l ) -p 'Select an event:' $DMENU_ARGS )"

		# Confirm reminder deletion
		confirm='N'
		confirm="$( dmenu -p "$oldEvent | Delete event from ${remDir##*/} ?" <<< $'y\nN' $DMENU_ARGS )"

		# Write reminder to reminder file
		if [ "${confirm,,}" = "y" ]; then
			sedOld="$( sed -e 's/[]\/$*.^.^|[]/\\&/g' <<< $oldEvent )"
			sed -i '/'"$sedOld"'/d' "$remDir"
		fi
		;;
	*) # Catchall -- exit
		;;
esac	

I bind this script (with the appropriate options) to a key in my window manager, and run remind as a daemon, so timed reminders (e.g. "go to a meeting in 10 minutes") pop up on the screen at the appropriate times, and when I want to view or edit my calendar I do it with this script.

Some details:

  • I keep my reminders in multiple files in one directory. In that directory, the file main.rem contains a bunch of include statements that tell remind which files to read. This script simply reads all files in the directory directory.

  • When creating an event, dmenu will provide suggestions for the event trigger and body. The trigger suggestion is mainly just to remind me of all of the syntax I use, and I often end up deleting most of it. The suggestion for the body makes it so that MSG %"Do a thing%" displays as "Do a thing" in the calendar, and "Do a thing in 2 days time" in the list of reminders.

Offline

#311 2016-05-13 17:43:56

cirquit
Member
Registered: 2016-05-13
Posts: 1

Re: Dmenu Hacking Thread

I'm very much a newby with bash, so suggestions are very much appreciated. I'm using dmenu with xmobar / xmonad. I needed to modify dmenu_run to run terminal based as well as gui programs, so I created a whitelist to check and run it accordingly. This is probably very basic, but maybe it'll help somebody. Here is a webm.

EDIT: Well, obviously I'm blind. Page 2. Could somebody explain to me why it's better to avoid substring-matching?

#!/bin/bash

# programs you want to start from the command line separated with space
cmdprogs='vim top'
# your terminal of choice
TERM=mate-terminal

# untouched dmenu_run
cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"}
if [ -d "$cachedir" ]; then
    cache=$cachedir/dmenu_run
else
    cache=$HOME/.dmenu_cache # if no xdg dir, fall back to dotfile in ~
fi
if stest -dqr -n "$cache" $PATH; then
    choice="$(stest -flx $PATH | sort -u | tee $cache | dmenu)"
else
    choice="$(dmenu < $cache)"
fi

prevIFS=$IFS
IFS=' '

# iterating through possible commandline specific programs
for prog in $cmdprogs; do
  if [[ $choice =~ $prog ]]; then  # if a match was found, start in terminal of choice
      $TERM -e $choice
      IFS=$prevIFS
      return 0
  fi
done

# if the program is not specified as a cmd program, start through shell
if [ $choice ]; then
    IFS=$prevIFS
    echo $choice | $SHELL &
fi

Last edited by cirquit (2016-05-13 19:51:09)

Offline

#312 2016-05-15 16:52:00

faiden
Member
Registered: 2014-03-08
Posts: 22

Re: Dmenu Hacking Thread

Posting my own try for a mpd/dmenu script (dunstify can be replaced with notify-send)

# Connection Details for the MPD server
IP="192.168.0.3"
PORT="6600"

# Check if MPD is runningi
nc -w 1 -z $IP $PORT || { dunstify "MPD:" "No connection to ${IP}:$PORT" && exit $?; }

MPC=$(mpc -h $IP -p $PORT)
MPC_PLAYLIST="$(mpc -h $IP -p $PORT playlist |nl -s ' - ')"

# Check the state of MPD
if [[ $MPC == *\[playing\]* ]]; then
	read -r MPC_TITLE <<<"$MPC"
	MPC_POSITION=${MPC##*#}
	MPC_POSITION="${MPC_POSITION%%/*}."
elif [[ $MPC == *\[paused\]* ]]; then
	read -r MPC_TITLE <<<"$MPC"
	MPC_POSITION=${MPC##*#}
	MPC_POSITION="${MPC_POSITION%%/*}."
	MPC_STATE="[Paused] "
else
	MPC_STATE="[stopped] "
fi

# show dmenu playlist and promp
DMENU_INPUT="$(echo "$MPC_PLAYLIST" |dmenu -i -p "$MPC_STATE$MPC_POSITION$MPC_TITLE" "$@")"

# MPD Controls
case $DMENU_INPUT in
"|")
	mpc -h $IP -p $PORT stop
	;;
">")
	mpc -h $IP -p $PORT next
	;;
"<")
	mpc -h $IP -p $PORT prev
	;;
"~")
	mpc -h $IP -p $PORT toggle
	;;
*)
	mpc -h $IP -p $PORT play ${DMENU_INPUT%% -*}
	;;
esac

I also have a question:
Is it possible for dmenu to have an item preselected in the list.
My script prints out the playlist but the selection is always on the first entry. How can I make it start on another entry? Like the current playing song.

Offline

#313 2016-05-21 09:19:11

Rasi
Member
From: Germany
Registered: 2007-08-14
Posts: 1,914
Website

Re: Dmenu Hacking Thread

Made a little todo manager with rofi:

It's kind of like a basic todo.txt, but uses a different file layout, so one can properly display it.
todos are colored and prioritized and for each todo one can assign an URL.

Screenshots/Code: https://github.com/carnager/dofi

Last edited by Rasi (2016-05-21 09:40:15)


He hoped and prayed that there wasn't an afterlife. Then he realized there was a contradiction involved here and merely hoped that there wasn't an afterlife.

Douglas Adams

Offline

#314 2016-05-29 23:24:09

Rasi
Member
From: Germany
Registered: 2007-08-14
Posts: 1,914
Website

Re: Dmenu Hacking Thread

After finding out about buku I made a frontend for it:
https://github.com/carnager/buku_run


He hoped and prayed that there wasn't an afterlife. Then he realized there was a contradiction involved here and merely hoped that there wasn't an afterlife.

Douglas Adams

Offline

#315 2016-06-12 04:55:32

Docbroke
Member
From: India
Registered: 2015-06-13
Posts: 1,433

Re: Dmenu Hacking Thread

dmenu based web-search/bookmarks/history/openurl script

#!/bin/bash

INFO() {
    cat <<EOF>&2
### DEPENDS ON ###
     "surfraw"-for keyword based search, you will need /usr/lib/surfraw in your path, so add below line to your .bashrc (uncommented)
     PATH=/usr/lib/surfraw:${PATH}
### CONFIGURATION ###
     place your browser in BROWSER=? line
	 place your bookmarks text file with 1 url/line, put it in second "BOOKMARKS=?" field replacing /tmp/bookmarks, comment out first "BOOKMARKS=?" line & grep -o line
     w3m users do not need to change BOOKMARKS=?
     default script uses rofi, to use dmenu uncomment the line starting with dmenu and comment out previous line starting with rofi
### USE ###
     enter text in rofi/dmenu field, it will be matched against bookmarks, <enter> to open selected bookmark
     to search specific sites use keyword as first argument ( like go for google, wi for wikipedia, aw for archwiki etc.) > read the script to find out all keywords
     to find out route with google map, "map delhi mumbai"
     if no keyword or url is used, entire argument will be searched with duckduckgo
     to use enterd text directly (not the matching bookmark) use <C-enter> (rofi only)
     to edit selected bookmark use <C-space> (rofi only)
EOF
}

while getopts h: help; do
    case $help in
    h|?) INFO && exit ;;
esac
done

shopt -s lastpipe

#echo -e "w3m
firefox" | rofi -dmenu -location 1 -l 10 -width 100 -font "Inconsolata 14" -p "which browser?"| read BROWSER

#[[ ! $BROWSER ]] && exit
#if [[ $BROWSER = w3m ]]; then st w3menu && exit ; fi

#BROWSER=firefox
BROWSER=vimb
# only for w3m bookmarks/ comment out if not using w3m
# BOOKMARKS=~/.w3m/bookmark.html
BOOKMARKS=~/.config/vimb/bookmark
#HISTORY=~/.config/lariza/history

# convert .w3m/bookmarks to simple text with 1 url/line; comment out if not using w3m
#grep -o 'http[^"]*' $BOOKMARKS > /tmp/bookmarks
#cat $BOOKMARKS > /tmp/bookmarks
# add w3m history to the list of bookmarks
# grep -o 'http[^"]*' $HISTORY >> /tmp/bookmarks
#cat $HISTORY >> /tmp/bookmarks
# add your plain text bookmarks here (do not edit or comment out if using w3m bookmarks), you can add tag after the bookmark bookmart url e.g., "www.google.co.in search googlesearch", use lariza-external-handler for adding bookmarks
#BOOKMARKS=/tmp/bookmarks
# use rofi to display bookmarks and select one
rofi -dmenu -location 1 -l 10 -width 100 -font "Inconsolata 14" -p $BROWSER: < "$BOOKMARKS" | read -a "url"
# use dmenu inplace of rofi
#/usr/bin/dmenu -l 10 -fn "Inconsolata 14" -p $BROWSER: < "$BOOKMARKS" | read -a url

[[ ! $url ]] && exit

duckimage() {
x=$@
$BROWSER "https://duckduckgo.com/?q=${x// /+}&ia=images&iax=1"
}
duckvideo() {
x=$@; $BROWSER "https://duckduckgo.com/?q=${x// /+}&ia=videos&iax=1"
}
DDG() {
x=$@; $BROWSER "https://duckduckgo.com/?q=${x// /+}"
}
MED() {
x=$@; $BROWSER "http://medical-dictionary.thefreedictionary.com/${x// /+}"
}
FLIPKART() {
x=$@; $BROWSER "https://www.flipkart.com/search?q=${x// /+}"
}
NAV() {
$BROWSER "https://maps.google.com/maps?saddr=$1&daddr=$2"
}
case "${url[0]}" in
    *.*|*:*|*/*)		     $BROWSER "${url[0]}" ;;
    aw|awiki)   archwiki    -browser=$BROWSER "${url[@]:1}" ;;
    wi|wiki)    wikipedia   -browser=$BROWSER "${url[@]:1}" ;;
    imdb)	imdb        -browser=$BROWSER "${url[@]:1}" ;;
    aur)	aur         -browser=$BROWSER "${url[@]:1}" ;;
    pkg)	archpkg     -browser=$BROWSER "${url[@]:1}" ;;
    ddg|S|DDG)	DDG			      "${url[@]:1}" ;;
    go|google)  google      -browser=$BROWSER "${url[@]:1}" ;;
    map) google -m   -browser=$BROWSER "${url[@]:1}" ;;
    nav)	NAV "${url[1]}" "${url[2]}" ;;
#    image)	google -i   -browser=$BROWSER "${url[@]:1}" ;;   
    image) duckimage "${url[@]:1}" ;;   
#    video)	google -v   -browser=$BROWSER "${url[@]:1}" ;;   
    video) duckvideo "${url[@]:1}" ;;
    news)	google -n   -browser=$BROWSER "${url[@]:1}" ;;      
    yt|youtube)	youtube     -browser=$BROWSER "${url[@]:1}" ;;
    ebay)	ebay        -browser=$BROWSER "${url[@]:1}" ;;
    fk|flipkart) FLIPKART "${url[@]:1}" ;;
    pubmed)	pubmed      -browser=$BROWSER "${url[@]:1}" ;;
    git|github)	github      -browser=$BROWSER "${url[@]:1}" ;;
    def) notify-send "$( sdcv --data-dir ~/dic/english/ "${url[@]:1}" )" && exit ;;
    guj) notify-send "$( sdcv --data-dir ~/dic/gujarati/ "${url[@]:1}" )" && exit ;;
    hin) notify-send "$( sdcv --data-dir ~/dic/hindi/ "${url[@]:1}" )" && exit ;;
    med)        MED                           "${url[@]:1}" ;;
    *)	if [[ $BROWSER != dillo ]]; then
	        duckduckgo -j -browser=$BROWSER "${url[@]}"
	    else
	        google -browser=$BROWSER "${url[@]}"
	    fi ;;
esac

EDIT: script updated

Last edited by Docbroke (2018-02-24 02:44:40)

Offline

#316 2016-06-12 12:19:49

null
Member
Registered: 2009-05-06
Posts: 398

Re: Dmenu Hacking Thread

Translate with dict:

#!/usr/bin/env bash

. "$XDG_CONFIG_HOME/dmenurc"
DICT_CMD="$(which dict)"
XCLIP_CMD="$(which xclip)"


DICT="${1?-No dictionary set}" || exit 1
WORD="${2}"
if [ -z "$WORD" ]; then
        WORD=$($XCLIP_CMD -o | $DMENU -p "Translate ($DICT):")
        if [ -z "$WORD" ]; then
                exit 1
        fi
fi


TRANSLATION=$($DICT_CMD -f -d "$DICT" "$WORD" 2>&1)
case $? in
        20)
                echo "$WORD" | $DMENU -p Nothing\ found:
                exit 1
                ;;
        21)
                WORD="$(echo "$TRANSLATION" | awk 'NR>1 {print $4}' | $DMENU -p "Nothing found for $WORD. Did you mean:")"
                if [ -n "$WORD" ]; then
                        TRANSLATION=$($DICT_CMD -f -d "$DICT" "$WORD" 2>&1)
                        if [ "$?" != "0" ]; then
                                exit 1
                        fi
                fi
                ;;
        39)
                echo "$DICT" | $DMENU -p "Invalid Database:"
                exit 2
                ;;
esac

echo "$TRANSLATION" | awk '/^   /{gsub(/^[[:space:]]+/, ""); gsub("; ", "\n"); print}' | $DMENU -p "$WORD" | $XCLIP_CMD -i

usage: ./dmenu_dict $dictonary [$word]
where $dictionary is one of the `dict -D` list.

Needs community/dictd and extra/xclip for clipboard support. If you don't want clipboard support just remove both occurences of $XCLIP_CMD.
Also - by default - dictd searches the internet for dictonaries it couldn't find locally. That can be a security hazard in combination with clipboards (password leaks and such). You should only use local dictornaries in combination with xclip output to dict.
Doesn't work for long texts (i.e. dict-gcide) because I only use it for translation of single words.

Last edited by null (2016-06-13 14:56:56)

Offline

#317 2016-06-13 10:24:41

chickenPie4tea
Member
Registered: 2012-08-21
Posts: 309

Re: Dmenu Hacking Thread

Docbroke wrote:

dmenu based web-search/bookmarks/history/openurl script

At the top of the script it says it requires surf raw, but I also see a line calling rofi

cat /tmp/bookmarks | rofi -dmenu -location 6 -lines 10 -width 100 -p $BROWSER: > /tmp/x

You can like linux without becoming a fanatic!

Offline

#318 2016-06-13 11:57:16

Docbroke
Member
From: India
Registered: 2015-06-13
Posts: 1,433

Re: Dmenu Hacking Thread

1. rofi is almost = dmenu, you can just replace "rofi -dmenu" with "dmenu", I am using rofi inplace of dmenu with few advantages.
2. "surfraw" not "surf raw", is used for search using specified websites, so it comes in picture when you use search-term like "imdb avatar", or "google obama", it also provide some more features, e.g., if you want to search google for images of sunflower use "google -i sunflower"
all commands like "wikipedia, webster, google, imdb, aur, archwiki" are provided by surfraw, it provides many more that can be added to this script depending on which sites you want to search.

EDIT: changed instruction in script about rofi/dmenu, thanks for pointing out

Last edited by Docbroke (2016-06-13 12:08:30)

Offline

#319 2016-06-13 16:11:09

Docbroke
Member
From: India
Registered: 2015-06-13
Posts: 1,433

Re: Dmenu Hacking Thread

This is another script for using "pass"-password manager with dmenu/rofi, it allows viewing complete-password in notification/adding new password/removing password entry & editing existing password.

#!/usr/bin/env bash
## define your terminal in "TERM=<your-terminal>, defaults to sakura
## assumes your password store in ~/.password-store (default)
## the script uses rofi (alised to dmenu in my setup), to use dmenu just replace "rofi -dmenu" with "dmenu"

TERM=sakura

shopt -s nullglob globstar

prefix=${PASSWORD_STORE_DIR-~/.password-store}
password_files=( "$prefix"/**/*.gpg )
password_files=( "${password_files[@]#"$prefix"/}" )
password_files=( "${password_files[@]%.gpg}" )

echo -e "password view\npassword edit\nnew entry\nremove entry" | rofi -dmenu -location 1 -lines 4 -width 100 -p SELECT: > /tmp/x

grep -o view < /tmp/x && printf '%s\n' "${password_files[@]}" | rofi -dmenu "$@" -location 1 -lines 10 -width 100 -p PASS: > /tmp/a && notify-send -u critical "$(pass show $(< /tmp/a) 2>/dev/null)" && exit
grep -o edit < /tmp/x && printf '%s\n' "${password_files[@]}" | rofi -dmenu "$@" -location 1 -lines 10 -width 100 -p PASS: > /tmp/a && $TERM -e pass edit $(< /tmp/a) && exit
grep -o new < /tmp/x && cat /dev/null | rofi -dmenu -location 1 -lines 10 -width 100 -p PASS: > /tmp/a && $TERM -e pass edit $(< /tmp/a) && exit
grep -o remove < /tmp/x && printf '%s\n' "${password_files[@]}" | rofi -dmenu "$@" -location 1 -lines 10 -width 100 -p PASS: > /tmp/a && $TERM -e pass rm $(< /tmp/a) 2>/dev/null && exit

Offline

#320 2016-06-21 10:09:50

Docbroke
Member
From: India
Registered: 2015-06-13
Posts: 1,433

Re: Dmenu Hacking Thread

This is dmenu/rofi based password manager (using pass) combined with notes manager (using vim).
Basically I just combined my two different scripts to use with single keybinding, and it works fine.

 
#!/usr/bin/env bash
## define your terminal in "TERM=<your-terminal>, defaults to sakura
## assumes your password store in ~/.password-store (default)
## the script uses rofi (alised to dmenu in my setup), to use dmenu just replace "rofi -dmenu" with "dmenu" and remove "-location, -lines", etc option upto & keeping -p
## you will need to create "~/.notes-store" folder to store your notes.
TERM=sakura

shopt -s nullglob globstar

prefix=${PASSWORD_STORE_DIR-~/.password-store}
password_files=( "$prefix"/**/*.gpg )
password_files=( "${password_files[@]#"$prefix"/}" )
password_files=( "${password_files[@]%.gpg}" )

fix=${NOTES_DIR-~/.notes-store}
notes_files=( "$fix"/**/*.txt )
notes_files=( "${notes_files[@]#"$fix"/}" )
notes_files=( "${notes_files[@]%.txt}" )

echo -e "password view\npassword edit\nnew password\nremove password\nnotes view\nnotes new/edit\nnotes remove" | rofi -dmenu -location 1 -lines 7 -width 100 -p SELECT: > /tmp/x

grep -o "password view" < /tmp/x && printf '%s\n' "${password_files[@]}" | rofi -dmenu "$@" -location 1 -lines 10 -width 100 -p PASS: > /tmp/a && notify-send -u critical "$(pass show $(< /tmp/a) 2>/dev/null)" && exit
grep -o "pasword edit" < /tmp/x && printf '%s\n' "${password_files[@]}" | rofi -dmenu "$@" -location 1 -lines 10 -width 100 -p PASS: > /tmp/a && $TERM -e pass edit $(< /tmp/a) && exit
grep -o "new password" < /tmp/x && cat /dev/null | rofi -dmenu -location 1 -lines 10 -width 100 -p PASS: > /tmp/a && $TERM -e pass edit $(< /tmp/a) && exit
grep -o "remove password" < /tmp/x && printf '%s\n' "${password_files[@]}" | rofi -dmenu "$@" -location 1 -lines 10 -width 100 -p PASS: > /tmp/a && $TERM -e pass rm $(< /tmp/a) 2>/dev/null && exit

grep -o "notes view" < /tmp/x && printf '%s\n' "${notes_files[@]}" | rofi -dmenu "$@" -location 1 -lines 10 -width 100 -p Notes: > /tmp/a && notify-send -u normal -t 900000000 "$(cat ~/.notes-store/$(< /tmp/a).txt 2>/dev/null)" && exit
grep -o "notes new" < /tmp/x && printf '%s\n' "${notes_files[@]}" | rofi -dmenu -location 1 -lines 10 -width 100 -p Notes: > /tmp/a && $TERM -e vim ~/.notes-store/$(< /tmp/a).txt && exit
grep -o "notes remove" < /tmp/x && printf '%s\n' "${notes_files[@]}" | rofi -dmenu "$@" -location 1 -lines 10 -width 100 -p Notes: > /tmp/a && $TERM -e rm ~/.notes-store/$(< /tmp/a).txt 2>/dev/null && exit

Offline

#321 2016-08-16 16:23:13

masque
Member
Registered: 2013-02-24
Posts: 25

Re: Dmenu Hacking Thread

masque wrote:

This is for unmounting devices mounted by udevil and devmon
(Just don't label your devices "[ALL]" smile )

With dmenurc I pass dmenu flags only, not the entire dmenu string, so I think you can replace it easily if you use rofi.

Fixed the issue with spaces and added an option to eject optical medias.

#!/usr/bin/env bash

conf="$XDG_CONFIG_HOME/dmenu/dmenurc"
[[ -r $conf ]] && . "$conf"

# where drives are mounted by udevil/devmon
media_mounts="/media/$USER"
#media_mounts="/run/media/$USER"

drive=$((awk -v mounts="$media_mounts/" '$0 ~ mounts { gsub(mounts,"",$2); gsub(/\\040/," ",$2); print $2 }' /etc/mtab; printf "[ALL]\n[Eject-Optical]") | dmenu "${dmenuopt[@]}" -p unmount: "$@")
case "$drive" in
    "")
        exit 0
        ;;
    "[ALL]")
        awk -v mounts="$media_mounts/" '$0 ~ mounts { system("udevil unmount " $2) }' /etc/mtab
        still_mounted=$(awk -v mounts="$media_mounts/" '$0 ~ mounts { gsub(mounts,"",$2); print $2 }' /etc/mtab)
        if [ -z "$still_mounted" ]; then
            notify-send Unmounted "Every shares and removable drives"
        else
            notify-send -u critical Error "There are still mounted devices: $still_mounted"
        fi
        ;;
    "[Eject-Optical]")
        udevil unmount /dev/sr0
        error=$?
        if [ $error -eq 0 ]; then
            eject -r
            notify-send Ejected "Optical disc"
        elif [ $error -eq 1 ]; then
            notify-send -u critical Error "Optical disc is busy"
        else
            notify-send -u critical Error "Something's very wrong! ;)"
        fi
        ;;
    *)
        udevil unmount "$media_mounts/$drive"
        error=$?
        if [ $error -eq 0 ]; then
            notify-send Unmounted "$drive"
        elif [ $error -eq 1 ]; then
            notify-send -u critical Error "$drive is busy"
        else
            notify-send -u critical Error "Something's very wrong! ;)"
        fi
esac

Offline

#322 2018-02-23 19:15:22

null
Member
Registered: 2009-05-06
Posts: 398

Re: Dmenu Hacking Thread

I was always annoyed by dmenu_run showing all executables while I'm only using it for launching gui applications. So here's a short replacement that only shows binaries that have a desktop entry in the usual paths while also checking for new binaries with the same mechanism as dmenu_run. It takes the first Exec= entry in each file, takes the basename of the defined binary and checks if it is a valid command (so it shows firefox in the menu instead of "/usr/lib/firefox/firefox %u" and ignoring all entries that don't match with a binary in $PATH. I.e. it doesn't work for pgAdmin4, because the binary is called pgadmin4). If you're missing a command just place a <name>.desktop in $HOME/.local/share/applications with Exec=<binary> or add a variable to the script.

#!/usr/bin/bash

DESKTOPPATH="/usr/share/applications $HOME/.local/share/applications"
DMENU_CACHE="$HOME/.cache/dmenu_guiapps"

if ! [ -f "$DMENU_CACHE" ] || stest -dqr -n "$DMENU_CACHE" $DESKTOPPATH; then
        find $DESKTOPPATH -name '*.desktop' -exec awk -F '[ =]' '
                /^Terminal=true/ { term=1; }
                /^Exec[^\/]*$/ { if (!term) cmds[$2] = 1; }
                END { for (key in cmds) print key; }
        ' '{}' \; | sort -b | uniq > $DMENU_CACHE
fi

cat "$DMENU_CACHE" | dmenu -i "$@" | ${SHELL:-"/bin/sh"} &

Thanks @Tribly for the awk script. It's way faster than the other way.

Last edited by null (2018-02-24 14:11:48)

Offline

#323 2018-02-23 19:54:13

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,449
Website

Re: Dmenu Hacking Thread

I'm pretty sure this would do the same:

find /usr/share/applications/ $HOME/.local/share/applications \
	-name '*.desktop' -exec awk -F"[ =]" '
		/^Terminal=true/ { term=1; }
		/^Exec[^\/]*$/ { if (!term) cmds[$2] = 1; }
		END { for (key in cmds) print key; }
	' '{}' \+ > $DMENU_CACHE
cat $DMENU_CACHE ...

EDIT: oops, I think you want ones that *dont* have terminal=true, right.  I just fixed that.

Last edited by Trilby (2018-02-23 19:55:53)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#324 2018-02-24 13:23:01

null
Member
Registered: 2009-05-06
Posts: 398

Re: Dmenu Hacking Thread

Thanks. I really need to get more into this awk magic smile

And especially thanks for this -F '[ =]'. I never thought having multiple seperators was a thing. That will greatly reduce my usage of gsub() big_smile
Edit: should have read awk(1) with more care. -F actually takes any regular expression. Nice.

Last edited by null (2018-02-24 13:26:15)

Offline

#325 2018-08-23 11:14:31

Unstack
Member
Registered: 2018-08-20
Posts: 3

Re: Dmenu Hacking Thread

dmenu hack for querying Google. [GIF Preview (>1mb)]

Tell me what you think.

Offline

Board footer

Powered by FluxBB