Menus Dynamiques dans pekwm

Bonjour!

Vous le savez peut-être, mais à l’instar du gestionnaire de fenêtre openbox, son cousin pekwm permet lui aussi d’afficher des menus dynamiques. Il a cependant la particularité de pouvoir affichier le résultat de scripts directement dans le menu, et non dans des sous menus.
Bref, cette fonction peut être très pratique si l’on veut éxécuter certaines actions simplement via un menu, ou alors se passer de zone de notification en ayant les infos voulues dans le menu.

Je propose que dans ce topic, chacun poste son pipemenu (menu dynamique) pour pekwm, afin que cela puisse servir aux autres ensuite.
Voici ce que j’ai fait jusqu’ici :
(Vous allez sûrement penser que c’est du bidouillage : c’est vrai, mes connaissances du bash sont très limitées. C’est pourquoi je serais ravi de recevoir vos commentaires, afin de m’expliquer ce que j’ai mal fait, ce que je pourrais améliorer, ce qui n’est pas propre, ce qui rend le script lourd ou lent… merci :slightly_smiling: )

Date et heure :
Rien de merveilleux, vous l’aurez sûrement fait vous même :

[code]#!/bin/sh
#pek-date.sh
#Ajoutez ceci dans le fichier ~/.pekwm/menu :
#Entry = “” { Actions = “Dynamic /path/to/the/script/pek-date.sh” }

date=$(date +%A\ %d\ %b\ %H:%M)
echo "Dynamic {"
echo " Entry = “$date” { Actions = "Exec osmo & " }"
echo "}"
exit
[/code]

Infos sur la batterie :

#!/bin/sh #Ajoutez ceci dans le fichier ~/.pekwm/menu : #Entry = "" { Actions = "Dynamic /path/to/the/script/pek-battery.sh" } echo "Dynamic {" echo " Submenu = \"Batterie : $(acpi -b | awk '{print $4}' | sed 's/,//g') \" { " echo "Entry = \" $(acpi -b | awk '{print $5}' | sed 's/,//g') restant\" { Actions = \"Exec source /dev/null & \" }" echo "}" exit;

On entame maintenant plus intéressant : une gestion de mpd, le lecteur de musique:
note : il faut avoir mpc d’installé.

on affichera la liste des artistes tout d’abord, puis ensuite a liste des chansons de l’artiste en question. Si on clique sur la chanson, elle est ajoutés à la liste de lecture. Pour éviter les doublons, si on rerajoute une autre piste, la précédente est supprimée.

[code]#! /bin/sh
#pek-mpd-alpha.sh
#script pour gérer mpd dans un menu de pekwm
#Ajoutez ceci dans le fichier ~/.pekwm/menu :

Entry = “” { Actions = "Dynamic /path/to/the/script/pek-mpd-alpha.sh 1 " }

#thuban@fritalk.org
#\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\O/\o/\o/\o/\o/\o/\o/\o/\o/\o/\Q/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/#
LISTE_ARTISTE="/tmp/liste_artiste"
CHEMIN="/home/xavier/Documents/Scripts/Pekwm" # chemin du dossier où sont enregistrés les scripts
mpc list artist | sort -f > $LISTE_ARTISTE
NB_ARTISTE=cat $LISTE_ARTISTE | wc -l
N=25 # nombre d’artistes à afficher en une fois
STATUS1=mpc current #Qu’est ce que joue mpd?
STATUS2=mpc | grep 'playing' | grep -Eo '[0-9]+:[0-9]+/[0-9]+:[0-9]+' #temps écoulé

#fonction qui affiche les artistes par la première lettre

#la fonction qui affiche les noms d’artistes
affiche_ () {
i=$1
while [ $i -le $(expr $1 + $N) ]
do
ARTISTE=cat $LISTE_ARTISTE | sed -n ${i}p
echo "Submenu = “$ARTISTE” {"
echo "Entry “” { Actions = “Dynamic $CHEMIN/pek-mpd-artiste2.sh ‘$ARTISTE’ &” }"
echo "}"
i=$(expr $i + 1)

done

}

echo “Dynamic {”
#on affiche le status de mpd que la première fois
if [ “$1” = “1” ]; then
#mpd joue :
if [ “$STATUS1” != “” ];then
echo “Submenu = “$STATUS1 $STATUS2” {” #status
else
#mpd est arrêté
echo "Submenu = “MPD : Ne joue pas” { "
fi

Un menu d’action pour mpd

echo “Entry = “Play-Pause” { Actions = " Exec mpc toggle & " }” #play/payse
echo “Entry = “Next” { Actions = " Exec mpc next & " }” #chanson suivant
echo “Entry = “Previous” { Actions = " Exec mpc prev & " }” #chanson précédente
echo "Separator {}"
fi
affiche_ $1
#si on n’est pas à la fin, on propose un sous menu pour afficher les N artistes suivants
if [ $i -le $NB_ARTISTE ]; then
echo "Submenu = “Plus…” {"
echo "Entry “” { Actions = “Dynamic $CHEMIN/pek-mpd-alpha.sh $i &” }"
echo "}"
fi
echo “}”

exit 0;

[/code]
L’autre script qui va avec :

[code]#!/bin/sh
#pek-mpd-artiste2.sh
#script pour gérer mpd dans un menu de pekwm, va avec pek-mpd-alpha.sh
#thuban@fritalk.org
#-----------------------------------------------------------------------------
#c’est une autre façon de faire pour ajouter les pistes
#De plus, avec l’autre script, la chanson suivante était TOUJOURS la première de la playlist…

#!!!les espaces dans les noms de fichier de passent pas toujours!!!
#remplacer la ligne “mpc find artist” par “mpc search artist” si besoin

#\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\O/\o/\o/\o/\o/\o/\o/\o/\o/\o/\Q/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/#
##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##|##
##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##A##

LISTE_CHANSON="/tmp/liste_chanson" # on enregistre la liste des chansons de l’artiste dans un fichier pour ne pas avoir à éxécuter cette commande tout le temps
v=$IFS
IFS=’
'
mpc find artist “$1” > $LISTE_CHANSON # on cherche l’artiste dans la bibliotheque

NB_CHANSON=cat $LISTE_CHANSON | wc -l # on compte combien de chansons de cet artiste existent

#La variable suivante donne le nombre de chansons différentes dans la bibliothèque
#Elle permet d’éviter d’avoir une liste de lecture avec des doublons, et qui s’agrandit à chaque éxécution du script

NB_CHANSON_LIB=mpc stats | grep "Songs" | awk '{print $2}'
NB_CHANSON_PLAYLIST=mpc playlist | wc -l

if [ $NB_CHANSON_PLAYLIST -lt $NB_CHANSON_LIB ] | [ $NB_CHANSON_PLAYLIST -gt $(expr $NB_CHANSON_LIB + 1) ] ;then
mpc clear
mpc ls | mpc add
NB_CHANSON_PLAYLIST=mpc playlist | wc -l
fi

if [ $NB_CHANSON_PLAYLIST -eq $NB_CHANSON_LIB ]; then # Si on n'a pas de doubles, on ajoute la chanson à jouer normalement
	echo "Dynamic {"
	
		i=1
		while [ $i -le $NB_CHANSON ]
		do		
		CHANSON=`cat "$LISTE_CHANSON" | sed -n ${i}p`
		echo "Entry = \"$CHANSON\" { Actions = \"Exec cat $LISTE_CHANSON | sed -n ${i}p | mpc add && mpc play $((NB_CHANSON_LIB+1)) & \" }"
		i=$(expr $i + 1)
		done
	echo "}"
	
else #Si on a déja ajouté une chanson à la playlist, on la supprime avant d'ajouter la nouvelle
echo "Dynamic {"
		
		i=1
		while [ $i -le $NB_CHANSON ]
		do		
		CHANSON=`cat "$LISTE_CHANSON" | sed -n ${i}p`
		echo "Entry = \"$CHANSON\" { Actions = \"Exec mpc del $NB_CHANSON_PLAYLIST && cat $LISTE_CHANSON | sed -n ${i}p | mpc add && mpc play $((NB_CHANSON_LIB+1)) & \" }"
		i=$(expr $i + 1)
		done
	echo "}"
fi
IFS=v

exit 0;

[/code]

Enfin, une gestion des fichiers. On se déplace dans l’arborescence, et ouvre les fichiers avec le programme souhaité. Ajout d’un sous menu pour les images, si plusieurs actions peuvent être envisagées.

[code]#!/bin/sh
#!/bin/sh
#pek-file.sh
#Script pour parcourir le dossier personnel dans pekwm
#jabber : thuban@fritalk.org
#Pour l’utiliser, ajoutez ceci dans le fichier ~/.pekwm/menu :
#Submenu = “FICHIERS :” {

Entry = “” { Actions = “Dynamic /path/to/the/script/pek-file.sh” }

}

#\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\O/\o/\o/\o/\o/\o/\o/\o/\o/\o/\Q/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/\o/#
#À améliorer :
#Ajout d’icones (fait partiellement)

##Différentes variables pour simplifier les modifications
FILEMGR=“thunar” # file manager
TERM=“urxvt” # émulateur de terminal

CHEMIN="/home/xavier/Documents/Scripts/Pekwm" # chemin du dossier où sont enregistrés les scripts

on liste le contenu du répertoire courant.

liste_ () {
LISTE=ls -1 -F --sort=extension $PWD
echo “$LISTE”
}

Cette fonction permet d’afficher un menu en fonction du type de fichier

action_ () {
case $1 in
ls: ) echo “” #on n’affiche pas les erreurs retournée par ls
;;
*/ ) echo "Submenu = “$1” {"
echo "Entry “” { Actions = “Dynamic cd ‘$PWD/$1’ && $CHEMIN/pek-file.sh &” }"
echo “}”

	;;
	*.mov | *.avi | *.wma | *.mpg | *.mkv | *.flv | *.wmv | *.mp4 | *.AVI | *.ogm | *.ogg ) 
				echo "Entry = \"$1\" { Icon = \"video.png\"; Actions = \"Exec mplayer '$PWD/$1' & \" }" 
	;;
	*.odt | *.doc | *.xls | *.ods | *.ppt | *.opt ) 
				echo "Entry = \"$1\" { Icon = \"document.png\"; Actions = \"Exec soffice '$PWD/$1' & \" }"
	;;	
	*.abw ) 
				echo "Entry = \"$1\" { Icon = \"document.png\"; Actions = \"Exec abiword '$PWD/$1' & \" }"
	;;
	*.gnumeric )
				echo "Entry = \"$1\" { Icon = \"document.png\"; Actions = \"Exec gnumeric '$PWD/$1' & \" }"
	;;
	*.gba )
				echo "Entry = \"$1\" { Actions = \"Exec gvba '$PWD/$1' & \" }"
	;;
	*.png | *.jpg | *.JPG | *.jpeg | *.gif | *.bmp | *.tiff )
				echo "Submenu =  \"$1\" {"
				echo "Entry = \"Ouvrir avec gimp\" {Actions = \"Exec gimp '$PWD/$1' & \" }"
				echo "Entry = \"Ouvrir avec feh\" {Actions = \"Exec feh -x '$PWD/$1' & \" }"
				echo "Entry = \"Diaporama ici\" {Actions = \"Exec feh -x -r '$PWD' & \" }"
				echo "Entry = \"Définir comme fond d'écran\" {Actions = \"Exec feh --bg-scale '$PWD/$1' & \" }"
				echo "}" 
	;;
	*.gp4 | *.gp3 | *.gtp ) 
				echo "Entry = \"$1\" { Icon = \"musique.png\"; Actions = \"Exec tuxguitar '$PWD/$1' & \" }"
	;;
	*.txt | *.py | *.c | *.h | *.sh ) 
				echo "Entry = \"$1\" { Icon = \"mousepad.png\"; Actions = \"Exec geany '$PWD/$1' & \" }"
	;;
	*.ogg | *.mp3 | *.flac | *.wma | *.wav ) 
				echo "Entry = \"$1\" { Icon = \"musique.png\"; Actions = \"Exec smplayer -add-to-playlist '$PWD/$1' & \" }"
	;;
	*.pdf ) 
				echo "Entry = \"$1\" { Icon = \"document.png\"; Actions = \"Exec evince '$PWD/$1' & \" }"
	;;

esac

}
#on commence le menu
echo "Dynamic {“
v=$IFS
IFS=’
'
NB=liste_ | wc -l
i=1
while [ $i -le $NB ]
do
ELEMENT=”$(liste_ | sed -n ${i}p)"
action_ $ELEMENT
i=$(expr $i + 1)
done
echo "Separator {}"
echo "Entry = “Ouvrir dans $FILEMGR” { Actions = "Exec $FILEMGR ‘$PWD’/ & " }"
echo "Entry = “Terminal ici” { Actions = "Exec cd ‘$PWD’ && $TERM & " }"
echo "Entry = “Rechercher ici” { Actions = "Exec catfish ‘$PWD’/ & " }"
echo "}"
IFS=v
exit 0;

[/code]

Voila, à vos claviers!

ps : comme le dit kna, c’est sous licence WTFPL

edit : les soucis d’espaces sont résolus. Tous les scripts sont mis à jour pour fonctionner avec sh, donc partout.

un nouveau menu, pour afficher des fortunes :

#!/bin/sh #pek-date.sh #Ajoutez ceci dans le fichier ~/.pekwm/menu : #Entry = "" { Actions = "Dynamic /path/to/the/script/pek-fortunes.sh" } FORTUNE=/tmp/pek-fortune /usr/games/fortune > $FORTUNE LIGNES=`cat $FORTUNE | wc -l` echo "Dynamic {" for i in $(seq 1 $LIGNES) do echo " Entry = \"$(cat /tmp/pek-fortune | sed -n ${i}p)\" { Actions = \"Exec source /dev/null & \" }" done echo "}" exit 0;

Si tu veut licencier tes scripts il faut mettre ça dans le source :

[code] LICENCE PUBLIQUE RIEN À BRANLER
Version 1, Mars 2009

Copyright © 2009 Sam Hocevar
14 rue de Plaisance, 75014 Paris, France

La copie et la distribution de copies exactes de cette licence sont
autorisées, et toute modification est permise à condition de changer
le nom de la licence.

     CONDITIONS DE COPIE, DISTRIBUTON ET MODIFICATION 
           DE LA LICENCE PUBLIQUE RIEN À BRANLER 
  1. Faites ce que vous voulez, j’en ai RIEN À BRANLER. [/code]

Sinon pour ton problème de nom de fichier regarde du coté de la variables IFS.
Pour une boucle comme ça :

for i in `ls *.png` ; do echo $i; done
tu fais ça :

v=$IFS IFS=' ' for i in `ls -1 *.png` ; do echo $i; done IFS=v
D’ailleur tu devrais faire ça :

for i in *.png ; do echo $i; done

Très sympa tes scripts, je réinstalle pekwm et je teste ça pour voir :smt002

Merci beaucoup pour l’idée Misterfreeze! Cependant, tu voudrais bien m’expliquer ce qu’est la variable IFS, et ce que fais ton code de différent au mien s’il te plaît? Je vois que tu listes les fichiers en 1 colonne, tu dis que IFS correspond à un retour à la ligne… mais je suis vite perdu. IFS désigne la séparation entre les fichiers? Mais que viens faire le “v” alors?
Enfin, je comprend pas tout… :blush:

Merci aussi pour la précision pour alléger l’écriture. :smiley:

Je ne pense pas les licencier, ils n’en valent pas la peine. Je disais ça simplement pour que personne n’hésite à les améliorer :slightly_smiling: .

[quote=“thuban”]Merci beaucoup pour l’idée Misterfreeze! Cependant, tu voudrais bien m’expliquer ce qu’est la variable IFS, et ce que fais ton code de différent au mien s’il te plaît? Je vois que tu listes les fichiers en 1 colonne, tu dis que IFS correspond à un retour à la ligne… mais je suis vite perdu. IFS désigne la séparation entre les fichiers? Mais que viens faire le “v” alors?
Enfin, je comprend pas tout… :blush: [/quote]
Tu as tout compris de toi même. IFS (Internal Field Separator) c’est ce qui permet de séparer les fichiers entre autre. Mais c’est utilisé dans pleins d’endroit donc il vaut mieux sauvegarder sont ancienne valeur avant de la modifier.

C’est pas un allègement de l’écriture, c’est une bonne pratique et bien plus performant. ls ne sert strictement à rien pour ce genre de chose.

A oui tu peut aussi je pense changer ton shaban pour /bin/sh. C’est probablement légèrement plus léger et surtout plus portable (bash n’existe pas partout).

J’ai tout compris! Je vois mieux maintenant pourquoi tu listais tout en 1 colonne. Merci beaucoup! je vais réadapter tout ça à la fin de la semaine.

/bin/sh est plus léger que bash alors?

En fait si tu utilise squeeze ou sid c’est un lien vers dash qui est je crois bien plus léger car plus limité.

Je “plussoie” pour dash

Euh, je vais poser une question bête, mais est-ce qu’il permet d’interpréter toutes les commande tout de même?
J’ai essayé de changer pour le script pek-mpd-alpha.sh, mais du coup il ne fonctionne plus… (enfin j’ai pas trop cherché…)
Il me dit :

je met à jour les scripts dès que possible!

edit : je voudrais faire quelque chose, mais est-ce que parce que mon cerveau ne veut plus fonctionner après un exam, ou je ne sais pas quoi, je ne trouve pas. En fait, je voudrais pouvoir obtenir tous les mots d’un fichier commençant par une lettre précise. Par exemple, dans mon fichier, j’ai

ACDC Bach Beethoven ZZ top
Je voudrais obenir juste les mots commençant par B, comment puis-je faire?

Bonsoir,[quote=“thuban”] En fait, je voudrais pouvoir obtenir tous les mots d’un fichier commençant par une lettre précise. Par exemple, dans mon fichier, j’ai

ACDC Bach Beethoven ZZ top
Je voudrais obenir juste les mots commençant par B, comment puis-je faire?[/quote]Si tu mets un mot par ligne, $ cat fichier |grep B.devrait suffir.

Je dirais même plus :

et si tu veux qui commence par B ou b :

Merci les amis! :slightly_smiling:
j’avais cherché du côté de grep, mais j’ai vraiment du mal avec lui.
Du boulot m’attend après les partiels :slightly_smiling:

edit : je voulais savoir si /bin/dash était tout de même capable de comprendre les boucles for, car le problème semble venir de là. Il faut que je l’écrive différement?
edit2 : on dirait que oui :
extrait du man dash :

[code] The syntax of the for command is

       for variable [ in [ word ... ] ]
       do   list
       done

[/code]

Utilise un while :

i=0 while [ $i -lt 10 ]; do (($i++)) # ou i=$(expr $i + 1) done;

Et non il ne faut pas utiliser dash, mais sh. sh c’est le bourn shell c’est le standard POSIX (celui que tu trouveras aussi bien sous GNU/Linux, *BSD, GNU/Hurd, Solaris, AIX,… même sous MacOS) bref dans tout les unixs. Utiliser les standard c’est vraiment une bonne pratique.

En pratique tout les shell connu (bash, dash, tcsh, zsh,…) ont des modes de compatibilités avec le bourn shell (sh). Si tu crée un lien vers l’un d’eux qui s’appelle sh et que tu les lance à travers ce lien, ils se lancent en mode compatible sh. D’ailleurs si tu fais un ls -l /bin/sh tu verras quel shell est utiliser pour émuler sh sur ta machine.
Moi par exemple :

$ ls -l /bin/sh lrwxrwxrwx 1 root root 4 2009-05-06 08:42 /bin/sh -> dash
c’est dash.

Le problème avec bash c’est qu’il se permet certaines libertés avec la norme. Il autorise des choses en trop, ça conduit à de mauvaises pratique et on croit faire des scripts standard alors qu’on en fait pas. C’est dans ce but que Debian à développé dash qui est le nouveau sh à partir de squeeze (à la place de bash).

Voila

je pensais me rabbatre sur une bouclie while, mais je me demandais s’il n’y avait pas une version pour dash de la boucle for que j’utilisais.
Ah oui, quand je parle de dash, du man de dash, etc, c’est parce que c’est celui qui est lié à sh, donc c’était pour tester. Merci tout de même pour les précisions, ça ne fait pas de mal!

hs : je vois que tu mentionne GNU/hurd. Il s’agit d’un autre type de noyaux? (bon ok, je file sur wikipedia :slightly_smiling: )

[quote=“MisterFreez”]Utilise un while :

i=0 while [ $i -lt 10 ]; do (($i++)) # ou i=$(expr $i + 1) done;

Voila[/quote]
Je ne sais pas si c’est normal, mais dash ne comprend pas le “(($i++))”, mais comprend le “i=$(expr $i + 1)” .
D’ailleurs, le expr signifie que l’on fait un calcul?

Je sais pas soit je l’ai mal écris soit le bourn shell ne sait pas gérer cette syntaxe je sais plus.

[quote=“thuban”] mais comprend le “i=$(expr $i + 1)” .
D’ailleurs, le expr signifie que l’on fait un calcul?[/quote]
man expr :wink:

En revoyant la syntaxe du $(()), je viens de voir seq que tu peut utiliser ainsi :

for i in $(seq 0 9) ; do # blabla done;
C’est pas mal, sinon pour la syntaxe de $(()), j’ai toujours pas compris comment ça marche :laughing:

% time bash -c 'for i in *; do echo "$i">/dev/null; done' bash -c 'for i in *; do echo "$i">/dev/null; done' 0,00s user 0,01s system 51% cpu 0,023 total % time dash -c 'for i in *; do echo "$i">/dev/null; done' dash -c 'for i in *; do echo "$i">/dev/null; done' 0,00s user 0,00s system 49% cpu 0,008 total
Au fait pour les bench entre dash et bash

hum, très intéressant le bench, on voit la différence là!
Eh bien merci pour les précisions une fois de plus! il faut vraiment que je me fasse un pense-bête pour toutes les petites syntaxes en script shell.
Décidément, il y a des man pour tout, c’est génial!

Tu aurais une source, un lien web, un bouquin parlant du shell (et pas que du bash)?

Je sais qu’il existe quantité de bouquin sur le scripting shell. J’en ai malheureusement jamais ouvert un donc je saurais pas te dire. Dans le temps et toujours des fois à l’heure actuelle, il y a des gens qui imprimaient les man. Si tu préfère les avoir sous forme papier.