Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: dmenu, het zwitsers zakmes van de Linux desktop  (gelezen 1300 keer)

Offline MKe

  • Lid
dmenu, het zwitsers zakmes van de Linux desktop
« Gepost op: 2021/09/21, 21:23:55 »
In het draadje https://forum.ubuntu-nl.org/index.php?topic=109498.0 kwam ter sprake dat ik eens wat over dmenu zou schrijven.

Dmenu is een heel klein programmaatje gemaakt door de mensen van suckless. Het volgt de filosofie van Linux (doe 1 ding) tot in het extreme. Dmenu van zichzelf doet namelijk vrijwel niets. Het enige wat het doet is het accepteren van een lijst via de stdin. Vervolgens geeft dmenu dat weer en kan de gebruiker een item uit de lijst kiezen. De keuze wordt 'gepiped' naar de stdout. Door dit in een bash script te vatten kun je er oneindig veel dingen mee doen als je maar creatief genoeg bent. De bekendste toepassing is als licht gewicht app launcher in veel lichte desktop omgevingen. Dit script wordt automatisch geinstalleerd met dmenu en heet dmenu_run. De werking is vergelijkbaar met de dash in Ubuntu.

Om dmenu te gebruiken moet je het eerst installeren vanuit de Ubuntu repositories met sudo apt install dmenu.

Hier volgt een voorbeeld om heel simpel de werking te demonstreren van dmenu.
Om de werking van dmenu te zien zou je het volgende in de commandline kunnen typen:
# de \n betekent een nieuwe regel, zoals in een file.
echo -e "een\ntwee\ndrie\nvier" | dmenu
Je kunt met de cursortoetsen een van de vier opties selecteren en dan op enter drukken. Let op hoe dmenu  de gekozen waarde print in de commandline. Dmenu kan dus een gebruiker iets laten selecteren en dat doorgeven aan een volgend programma. Door slimme scriptjes eromheen te maken kun je hier hele nuttige dingen mee doen.

Bijvoorbeeld, een script om een proces te "killen".
Waarschuwing, wees voorzichtig want als je het verkeerde proces killed dan kan je linux crashen en moet je opnieuw opstarten!. Wil je toch niets killen, druk dan op de escape toets die als Cancel werkt of type "Nee" als het scriptje om een bevestiging vraagt:
#!/usr/bin/env bash
lines="-l 20"

selected="$(ps -a -u $USER | \
            dmenu -i -p "Zoek process en kill:" \
            $lines | \
            awk '{print $1" "$4}')";

# killen van een proces kan grote gevolgen hebben
# dus wordt er hier eerst een bevestiging gevraagd
# bij selectie "Nee" gebeurt er niets
if [[ ! -z $selected ]]; then

    answer="$(echo -e "Ja\nNee" | \
            dmenu -i -p "$selected zal worden gekilled, weet je het zeker?" \
            $lines )"

    if [[ $answer == "Ja" ]]; then
# vind het ID van het process
        selpid="$(awk '{print $1}' <<< $selected)";
        kill -9 $selpid # kill het proces
    fi
fi

exit 0
Voor de beginneling: kopieer bovenstaande script in een tekst bestand, noem het b.v. kill.sh. Sla dit op in je home. Run het door de commandline te openen in te runnen met bash kill.sh
Morgen een ander voorbeeld.
« Laatst bewerkt op: 2021/09/21, 21:26:18 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #1 Gepost op: 2021/09/22, 09:12:43 »
Een leuk en nuttige toepassing. Het volgende scriptje scant je Documents folder in je home map naar pdf files zodat je ertussen kunt zoeken. Na selectie opent het pdf bestand in je pdf viewer. Ik heb hier evince als pdf viewer ingesteld, dit is de standaard pdf viewer in de normale Ubuntu. Je moet de variabel "ROOT" aanpassen naar de pdf viewer die je gebruikt op je systeem. Je kunt ook de ROOT aanpassen om in andere folders te zoeken.
Natuurlijk is dit ook aan te passen voor andere bestand types als jpg etc.

Ik ga niet heel diep in op bash programmeren, maar wat er hier gebeurt is dat het script de pdf files zoekt met een simpele find commando. De uitkomst daarvan wordt doorgegeven aan dmenu. Nadat je een document gekozen hebt wordt het bestand geopend met de geconfigureerde reader.

#!/bin/bash
ROOT="${HOME}/Documents/"
READER="evince"

FILE=$(find $ROOT -type f -iname "*.pdf" | dmenu -l 30)

if [[ "$FILE" == *.pdf ]]
then
    $READER "$FILE"
fi

FF een opmerking:  ik start deze scripts met een toetsen combinatie. Ik kan niet adviseren hoe dat in te stellen op je desktop omdat dit heel erg desktop specifiek is.
« Laatst bewerkt op: 2021/09/22, 12:22:04 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline vanadium

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #2 Gepost op: 2021/09/22, 10:37:01 »
Zoiets kan je eenvoudig uitbreiden om alle bestanden in je Documents folder te doorzoeken, en bij selecteren te laten openen met het geassocieerde programma. Gebruik dan als commando "xdg-open". Geeft je heel vlug toegang tot een bestand diep in je folderstructuur.

Op tragere computers met een klassieke harde schijf kan dit wat trager worden. Hier kan je dan "bufferen": je laat bij het inloggen het "find" commando de resultaten uitschrijven naar een tekstbestand (of je kan dat via een cron-job bijvoorbeeld elk uur herhalen). Bij het oproepen van dmenu stuur je dan het bestand ernaartoe:
FILE=$(cat .cache/documents.txt | dmenu -l 30)

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #3 Gepost op: 2021/09/22, 10:51:38 »
Zoiets kan je eenvoudig uitbreiden om alle bestanden in je Documents folder te doorzoeken, en bij selecteren te laten openen met het geassocieerde programma. Gebruik dan als commando "xdg-open". Geeft je heel vlug toegang tot een bestand diep in je folderstructuur.

Op tragere computers met een klassieke harde schijf kan dit wat trager worden. Hier kan je dan "bufferen": je laat bij het inloggen het "find" commando de resultaten uitschrijven naar een tekstbestand (of je kan dat via een cron-job bijvoorbeeld elk uur herhalen). Bij het oproepen van dmenu stuur je dan het bestand ernaartoe:
FILE=$(cat .cache/documents.txt | dmenu -l 30)
Klopt, een andere mogelijkhed zou zijn om mlocate te gebruiken. Die buffert automatisch.

Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #4 Gepost op: 2021/09/22, 11:06:57 »
Geinig, dat dmenu! Heb je pdf-voorbeeld geprobeerd en dat werkt prima. Nu nog even creatief zien te worden om hier meer mee uit te halen. ;) Dank voor de tip.

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #5 Gepost op: 2021/09/22, 12:44:41 »
Ook een leuke toepassing, al is het misschien niet relevant voor iedereen.

Als je meerdere linux machines hebt waar je wel eens via ssh op wilt inloggen kun je een ssh menu maken met daarin alle computers waar je wel eens naar toe hebt gessh'ed (goed nederlands :) ). Het script start een terminal op met de ssh verbinding. Ik gebruik zelf de st terminal, maar misschien moet je dus de term_cmd aanpassen aan je eigen terminal emulator. Het script houdt er ook rekening mee dat je misschien de mosh shell gebruikt i.p.v. ssh al zal dit niet vaak voorkomen:

#!/usr/bin/env bash

term_cmd=${TERM_CMD:-st -e}
ssh_cmd=${SSH_CMD:-ssh -t}
ssh_config=${SSH_CONFIG_FILE:-$HOME/.ssh/config}
remote_cmd=${REMOTE_CMD}

ssh_hosts=( $(grep "^Host\s\+[^*]" $ssh_config | cut -d " " -f 2-) )
ssh_host=$(printf '%s\n' "${ssh_hosts[@]}" | dmenu -i "$@")

if [ -n "$ssh_host" ]; then
  ssh $ssh_host hash mosh-server 2> /dev/null
  if [ $? -eq 0 ]; then
    ssh_cmd="mosh"
  fi
  $term_cmd $ssh_cmd $ssh_host $remote_cmd
fi
« Laatst bewerkt op: 2021/09/22, 13:10:13 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline vanadium

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #6 Gepost op: 2021/09/22, 14:08:09 »
Iets wat velen wel eens nuttig zouden kunnen vinden: snel standaardtekst invoegen, bijvoorbeeld de aanhef van een email, je adres, stukken code, ik gebruik dit zelfs voor het invoegen van vreemde karakters.

Waar je de tekst wil invoegen, druk je op de sneltoets die je aan het script hebt toegewezen. Je kiest het fragment, en na een druk op Enter wordt de tekst ingevoegd.

De tekstfragmenten zijn aanwezig in afzonderlijke tekstbestanden. De naam van het bestand is wat je ziet in het menu. Stel, je hebt een tekstfragment "email" dat je email adres bevat. Je drukt de sneltoets (bij mij Ctrl+Shift+,). "em" typen kan al voldoende zijn om enkel dat fragment te zien. Op Enter drukken, en het volledige email adres wordt ingevoegd

Hier is het script:

#!/usr/bin/env bash

# Plakt de inhoud van een gekozen tekstfragment.
# Afhankelijkheden: dmenu, xsel, xdotool

SNIPPYDIR=${HOME}/Documents/Configuration/Snippy/ ## Waar de tekstbestanden komen
OLDSELECT=$(mktemp)                               ## Tijdelijk bestand voor origineel klembord
DMENU="dmenu -l 30"

# De huidige inhoud van het klembord wordt bewaard om later te herstellen
xsel -bo > "$OLDSELECT"

# Selectie van de tekstclip
SELECTION=$(ls "$SNIPPYDIR" -1 | $DMENU)
head -c -1 "$SNIPPYDIR"/"${SELECTION}" | xsel -bi
# Plakken
xdotool key Shift+Insert

# Herstel origineel klembord
sleep 0.5s   # Even wachten is nodig wanneer in Firefox.
xsel -bi < "$OLDSELECT"
rm "$OLDSELECT"
« Laatst bewerkt op: 2021/09/22, 14:16:19 door vanadium »

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #7 Gepost op: 2021/09/22, 15:03:05 »
Mooie toepassing, vanadium simpel en doeltreffend.

Deze heb ik van suckless zelf gejat, een simpele todo list. Hij maakt een file ".todo" aan in je home. Als je een nieuwe tekst typed wordt dat toegevoegd aan de todolist, selecteer je echter een van de aanwezige todo items, dan verwijderd hij dat weer uit de lijst.

#!/bin/sh
#
# Write/remove a task to do later.
#
# Select an existing entry to remove it from the file, or type a new entry to
# add it.
#

file="$HOME/.todo"
touch "$file"
height=$(wc -l "$file" | awk '{print $1}')
prompt="Add/delete a task: "

cmd=$(dmenu -l "$height" -p "$prompt" "$@" < "$file")
while [ -n "$cmd" ]; do
  if grep -q "^$cmd\$" "$file"; then
grep -v "^$cmd\$" "$file" > "$file.$$"
mv "$file.$$" "$file"
        height=$(( height - 1 ))
  else
echo "$cmd" >> "$file"
height=$(( height + 1 ))
  fi

cmd=$(dmenu -l "$height" -p "$prompt" "$@" < "$file")
done

exit 0

Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #8 Gepost op: 2021/09/22, 17:13:00 »
Haha, jullie zijn lekker bezig hier!
Je kunt natuurlijk ook een toedoelijst, al dan niet via een sneltoets, in een editor openen. ;)
Maar ik volg jullie "gefreak" met belangstelling...

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #9 Gepost op: 2021/09/22, 17:17:23 »
Haha, jullie zijn lekker bezig hier!
Je kunt natuurlijk ook een toedoelijst, al dan niet via een sneltoets, in een editor openen. ;)
Maar ik volg jullie "gefreak" met belangstelling...
klopt, er zijn een miljoen manieren om een todo list te maken. Dit is er gewoon nog een. Wel bijzonder dat een simpele tool als dmenu dit kan en het zou maar net in je workflow passen ;)

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #10 Gepost op: 2021/09/23, 12:49:36 »
De volgende is ook weer niet voor iedereen van toepassing. Ik heb dit geschreven omdat ik niet gebruik maak van standaard desktop omgevingen als Gnome, XFCE en KDE en ik graag een handige manier wil hebben om af te kunnen sluiten of uit te loggen. Ik herinner me dat Gnome3 ook heel lang geen standaard mogelijkheid had om af te sluiten, ik weet niet of dat nog steeds zo is. Maar het volgende script geeft je een dmenu met opties om uit te loggen,  te rebooten of de computer uit te zetten. Details in mijn blog hierover: (https://mke21.wordpress.com/2020/05/27/08-een-afsluit-menu/)

Zorg ervoor dat je de juiste regel voor uitloggen activeert door de "#" voor die regel te verwijderen en de anderen te inactiveren met een # ervoor. Hier is de regel voor Gnome geactiveerd.

#!/usr/bin/env bash

# eerst het lijstje maken, let op de \n
action_list="logout\nreboot\npoweroff"

# nu de lijst aan dmenu voeden en dmenu uitvoeren
# de keuze komt in de variable 'action'
action=$(echo -e $action_list | dmenu "$@" )

# nu bepalen wat te doen aan de hand van de waarde in
# variable $action
case $action in
  logout)  # als logout gekozen
    # Gnome3
    gnome-session-quit ;;
   
    # DWM
    # killall dwm ;;
   
    # XFCE
    # xfce4-session-logout ;; 
   
    # KDE
    # qdbus org.kde.ksmserver /KSMServer logout 0 0 1
  reboot) # reboot gekozen?
    systemctl reboot;;
  poweroff)
    systemctl poweroff ;;
esac # einde van keuzes
« Laatst bewerkt op: 2021/09/23, 13:10:34 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline vanadium

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #11 Gepost op: 2021/09/23, 15:33:28 »
Je was me voor!  =D

Je kan die acties ook integreren in elk applicatiemenu (inclusief i3-dmenu-desktop of j3-dmenu-desktop) door er starters (.desktop bestanden) voor te maken in je .local/share/applications folder.

Ook dmenu kan opgezet worden om applicaties te tonen waarvoor een starter geïnstalleerd is (doorgaand  toepassingen met GUI), eerder dan elke mogelijk uitvoerbaar terminalcommando (dmenu_run). Met de i3 window manager komt het script i3-dmenu-desktop. Voor niet-i3 gebruikers is het veel handiger  j3-dmenu-desktop te installeren, standaard aanwezig in het Ubuntu softwarecentrum.

Voorbeeld van dergelijke starter: ~/.local/share/applications/system.shutdown.desktop

[Desktop Entry]
Type=Application
Exec=gnome-session-quit --power-off
Icon=system-shutdown-symbolic
Terminal=false
Categories=Utility;
Keywords=Shut;Turn off;
Name=Power Off
Comment=Shut down the system

(commando na "Exec=" eventueel aan te passen voor andere desktopomgevingen). Als dit bestand op de juiste plaat staat (~/.local/share/applications, /usr/local/share/applications), dan wordt dat automatisch opgepikt door het menusysteem van elke desktop (Gnome Shell, KDE, xfce, ...) en ook door j3-dmenu-desktop.

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #12 Gepost op: 2021/09/23, 16:14:34 »
Daar had ik nooit aan gedacht om daar een .desktop file voor te gebruiken. Aan de andere kant vindt ik het wel fijn om een speciaal menu daarvoor te hebben. Toch mooi dat er zoveel mogelijkheden zijn  =D
« Laatst bewerkt op: 2021/09/23, 17:00:23 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #13 Gepost op: 2021/09/23, 19:21:29 »
Nog een leuke, lijst van alle open vensters en daar tussen kiezen. Ik weet dat veel desktops ook zoiets hebben, maar ik vindt dit gemakkelijk om mijn handen niet van het toetsenbord te hoeven halen. Het grappige is dat dmenu een behoorlijk stuk van de functionaliteit van desktops kan leveren, al ziet het er misschien minder fancy uit. Op deze manier kan ik van een simpele windowsmanager (i3wm, dwm, openbox etc) een volledige desktop ervaring maken.

Voor dit script moet je wmctrl installeren.

#!/bin/sh

if [ "${@:-1}" == "1" ]
then
  win=`wmctrl -l | colrm 1 19 | sed '/xfce4-panel/d' | dmenu -i`
else
  win=`wmctrl -l | colrm 1 19 | sed '/xfce4-panel/d' | dmenu ${@:-1}`
fi

if [ "$win" == "" ]
then
  exit
elif [ "$win" == "Desktop" ]
then
  wmctrl -k on
else
  wmctrl -a $win
fi

Offline vanadium

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #14 Gepost op: 2021/09/23, 22:41:57 »
Hm, die blijkt toch niet te werken bij mij:
$ dmenuwin
/home/vanadium/.local/bin/dmenuwin: 3: [: 1: unexpected operator
usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]
             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]
/home/vanadium/.local/bin/dmenuwin: 10: [: unexpected operator
/home/vanadium/.local/bin/dmenuwin: 13: [: unexpected operator
wmctrl: option requires an argument -- 'a'

De uitvoer van lijn 4 lijkt mij ook niet juist: verkeerd stukje geknipt.
$ wmctrl -l | colrm 1 19
ium dmenu, het zwitsers zakmes van de Linux desktop — Mozilla Firefox
ium Videos
ium dmenuwin (~/.local/bin) - gedit

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #15 Gepost op: 2021/09/24, 13:31:30 »
Vreemd, het werkt hier wel op Manjaro XFCE en een gepatchte DWM.

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #16 Gepost op: 2021/09/25, 21:36:24 »
Dit is voor mensen die niet altijd een browser open willen hebben.
Googelen via dmenu en googler. Hiervoor moet je googler *sudo apt install googler' hebben en jq (sudo apt install jq).
Dit geeft je de mogelijkheid om een zoekterm in te voeren, vervolgens geeft dmenu een lijst van maximaal 20 resultaten waaruit je dan kunt kiezen. Vervolgens wordt de default browser geopend met de gekozen url.

Het is nog niet perfect. Ik gebruik grep om de juiste url te vinden nadat je dat geselecteerd hebt. Dit gaat fout als er 2x dezelfde omschrijving is. Verder wil ik nog een keer kijken of er ook een googler voor DuckDuckGo bestaat.

#!/bin/bash

SEARCH=$(echo "" | dmenu -p "google: ")

if [ -z "$SEARCH" ]
then
exit;
fi
RESULTS=$(googler -n 20 --json "${SEARCH}" | jq -r '.[] | [.title, .url] | @csv')
CHOICE=$(echo -e "${RESULTS}" | cut -d, -f1 | tr -d '"' | dmenu -l 40 -p "results: ")
if [[ ! -z "$CHOICE" ]]
then
URL=$(echo -e "${RESULTS}" | tr -d '"' | grep -F "${CHOICE}" | cut -d, -f2 | tr -d '"')
xdg-open "$URL"
fi
« Laatst bewerkt op: 2021/09/25, 21:45:07 door MKe »
Mijn blokkendoos blog: http://mke21.wordpress.com/

Offline vanadium

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #17 Gepost op: 2021/09/26, 12:00:26 »
Dan lijkt een aanpak, waar je uit het script de browser opstart met een URL voor de zoekmotor, een betere aanpak. Via dmenu vraag je de zoekterm op. Je start de browser, en die zal dan automatisch zoekresultaten van de gekozen zoekmotor weergeven.

  • Met "zoekterm=$(echo '' | dmenu -p 'Geef je zoekterm: ')" bekom je de zoekterm die de gebruiker ingeeft.
  • Zoeken op Duck Duck Go kan je met: 'https://duckduckgo.com/?q=Ubuntu Nederland'.
  • Eens je de zoekterm hebt, start je je voorkeursbrowser op met de URL.

Een minimaal script wordt dus:

#!/usr/bin/env bash
url='https://duckduckgo.com/?q='
zoekterm=$(echo '' | dmenu -p 'Geef je zoekterm: ')
xdg-open "$url$zoekterm"

De wizzards onder ons voegen een if statementje toe, dat de browser enkel opent als de zoekterm bestaat, of niet leeg is  ^-^
« Laatst bewerkt op: 2021/09/26, 12:03:33 door vanadium »

Offline MKe

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #18 Gepost op: 2021/09/26, 12:27:04 »
Dat is idd ook een optie. Met if statement is het dan:

#!/usr/bin/env bash
url='https://duckduckgo.com/?q='
zoekterm=$(echo '' | dmenu -p 'Geef je zoekterm: ')
if [[ ! -z "$zoekterm" ]]
then
    xdg-open "$url$zoekterm"
fi

Offline vanadium

  • Lid
Re: dmenu, het zwitsers zakmes van de Linux desktop
« Reactie #19 Gepost op: 2021/09/26, 13:54:02 »
Deze laatste vind ik toch veel beter, korter, directer, en eleganter volgens mij, want die maximaal 20 resultaten die door dat vorige script worden kunnen nu net die ene pagina missen die je zoekt. En je hoeft naast dmenu niets bij te installeren.