Miamondo "dieu n'a pas voulu autre chose que la liberté" (commandant massoud)
http://miamondo.e-monsite.com

Billets de miamondo

  • J'ai adopté Z-Shell

    Bonjour,

    Il y a quelques semaines, j'ai fait l'acquisition d'un très beau grimoire édité par la maison d'édition allemande Rheinwerk et qui traite de la programmation Shell. C'est bien dommage qu'une telle collection n'existe pas dans notre belle langue française car dans une bibliothèque, ça en jette. Je possède deux ouvrages de cette collection estampillée deutsche Qualität. Lorsque je les ouvre avec le petit cordon orange qui sert de marque-page, j'ai toujours le sentiment de me plonger dans la Bible pour méditer sur je ne sais quel épître de Saint Torvalds aux Linuxiens.

     

    Z2

     

    Et aujourd'hui, mes biens chers frères, en ce jour où nous sommes rassemblés pour un moment de partage sous la nef de cette magnifique basilique Notre-Dame-de-l'Internet, je vous propose de cheminer avec moi sur les terres de Z-Shell. Quoi? Mais non! Abruti! Ce n'est pas le batteur d'un groupe de Death Metal islandais, c'est le nom d'un puissant interpréteur en ligne de commande. En fait, c'est du bash mais avec une bonne dose de créatine.

     

    1. Installation sous Debian et Archlinux

    Sous Debian

     sudo apt update && sudo apt install zsh

    Sous Archlinux

     sudo pacman -Syu && sud pacman -S zsh

    Les paquets zsh-common et zsh-doc seront également installés.

     

    2. Définir zsh comme shell par défaut

    C'est probablement bash qui est votre shell par défaut. Pour le remplacer par zsh, il vous suffit d'entrer la commande suivante:

     chsh -s /bin/zsh

    Puis, vous rebootez. À la prochaine ouverture de session, quatre choix s'offrent à vous. Cliquez sur l'image ci-dessous:

     

    Z3

     

    Nous allons nous intéresser au choix (0) qui se contente de créer le fichier de configuration ~/.zshrc et d'y entrer juste un commentaire pour empêcher que ce questionnaire à choix multiple n'apparaisse à la prochaine ouverture de session. À vous ensuite de configurer zsh à votre guise. C'est cette option que personnellement j'ai choisie.

    Vous pouvez également choisir de créer vous-même le fichier caché ~/.zshrc et d'y entrer juste un commentaire. Ça revient au même:

     echo #configure > ~/.zshrc

    Enfin, vous pouvez choisir l'option (2) qui va vous offrir une configuration standard par défaut avec le thème adam1, un historique des recherches et une complétion bien pratique (Nous allons voir ça un peu plus bas). Vous aurez déjà en mains un outil fonctionnel.

     

    3. Configuration standard par défaut

     

     # Set up the prompt

     autoload -Uz promptinit
     promptinit
     prompt adam1

     setopt histignorealldups sharehistory

     # Use emacs keybindings even if our EDITOR is set to vi
     bindkey -e

     # Keep 1000 lines of history within the shell and save it to   ~/.zsh_history:
     HISTSIZE=1000
     SAVEHIST=1000
     HISTFILE=~/.zsh_history

     # Use modern completion system
     autoload -Uz compinit
     compinit

     zstyle ':completion:*' auto-description 'specify: %d'
     zstyle ':completion:*' completer _expand _complete _correct _approximate
     zstyle ':completion:*' format 'Completing %d'
     zstyle ':completion:*' group-name ''
     zstyle ':completion:*' menu select=2
     eval "$(dircolors -b)"
     zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
     zstyle ':completion:*' list-colors ''
     zstyle ':completion:*' list-prompt %SAt %p: Hit TAB for more, or the character to insert%s
     zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=* l:|=*'
     zstyle ':completion:*' menu select=long
     zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s
     zstyle ':completion:*' use-compctl false
     zstyle ':completion:*' verbose true

     zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
     zstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'

     

    4. Configuration personnalisée

    Comme je l'ai déjà écrit, j'ai choisi de faire moi-même ma configuration:

     

     autoload -Uz compinit

     compinit

     HISTFILE=~/.histfile
     HISTSIZE=1000
     SAVEHIST=1000

     bindkey -e

     autoload -U colors && colors
     PS1="%{$fg[green]%}%n%{$reset_color%}@%{$fg[red]%}%m%{$reset_color%}%{$fg[yellow]%}%~ %{$reset_color%}% $ %"

     RPROMPT="%*"

     # autoload -U promptinit && promptinit
     # prompt fade

     setopt auto_cd correct rm_star_wait

     

    • Lignes n° 1 et 2 : Activation de la complétion avec la touche Tab. Hyper pratique!
      • Prenons un exemple. Vous souhaitez supprimer une application que vous n'êtes pas sûr de pouvoir correctement orthographier. Vous savez qu'elle commence par un k. Vous entrez la commande suivante avant de presser la touche Tab:
     sudo pacman -S k

    • zsh va vous dérouler une liste d'applications commençant par un k. Vous n'avez plus qu'a vous déplacer avec la touche Tab puis à sélectionner en pressant la touche Entrée et le tour est joué.

     sudo pacman -S keyboard-configuration

    • Lignes n° 3, 4 et 5 : Configuration de l'historique qui peut accepter 1000 entrées.
    • Ligne n° 6 : Utiliser les raccourcis clavier emacs, même si la valeur d'EDITOR est vi
    • Lignes n° 7 et 8 : choix des couleurs pour l'invite de commande, c'est-à-dire le prompt. la ligne n° 11 peut vous paraître particulièrement ardue. En fait, c'est beaucoup plu simple qu'il n'y paraît :
      • fg[green] colore en vert %n (qui correspond à l'utilisateur). fg veut dire foreground (avant-plan).
      • reset_color réinitialise la couleur par défaut. @ est donc blanc.
      • fg[red] colore en rouge %m,qui correspond au nom d'hôte. (chez moi, c'est mws)
      • fg[yellow] colore en jaune le répertoire courant.
      • Cela nous donne:
     miamondo@mws ~ $

    • Ligne n° 9 : Configuration d'un second prompt à droite avec affichage de l'heure en format 24 heures et avec les secondes.
    • Lignes n° 10 et 11 : Possibilité de choisir un thème, par exemple fade. J'ai commenté les deux lignes pour empêcher leur exécution et conserver les couleurs que j'ai moi-même sélectionnées en lignes 10 et 11.
    • Lignes n° 12 : Cette commande setopt effectue trois opérations :
      • auto_cd : Complétion de la commande cd. Par exemple, vous entrez /e/a et vous pressez la touche TAB.
        • /etc/a va s'afficher.
        • Pressez la touche TAB encore une fois et sélectionner le répertoire souhaité (toujours avec la touche TAB), par exemple /etc/apt.
        • Pressez la touche Entrée. Vous vous retrouvez dans le répertoire /etc/apt. Très pratique!
      • correct : correction automatique d'une erreur de commande. Par exemple, vous entrez sl, une commande qui n'existe pas. zsh va vous demander si ce ne serait pas plutôt ls. Cette fonctionnalité est moins utile que la précédente et ne marche pas à tous les coups. J'ai, par exemple, entré la commande sodo pour obtenir les droits de super-administrateur. Je n'ai pas obtenu la correction souhaitée...
      • rm_star_wait : Demande de confirmation de destruction de répertoires. Si vous faites un rm-rf*, le Z-Shell va vous demander une confirmation au bout de dix secondes. C'est une sécurité que je n'ai pas osé tester... Mais je ne doute pas qu'elle fonctionne!

    Voilà le résultat avec un choix de couleurs personnalisées (à bâbord) ou bien avec le thème fade (à tribord).

     

    Z5 1      Z4

     

    Conclusion

    Sachez qu'il existe un site qui propose tout un tas de configurations, des modules mais également de la documentation :http://ohmyz.sh

    Nous voici parvenus au terme de cette modeste présentation de zsh, un shell qui m'a convaincu et que j'ai immédiatement adopté. Pour une découverte plus approfondie, vous pouvez entrer la commande man zsh. Vous pouvez même éditer directement un fichier pdf de ce manuel zsh en rajoutant les lignes suivantes à la fin du fichier de configuration ~/.zshrc:

    man()
    {
    /usr/bin/man $* > ~/temp.md
    if [ -s ~/temp.md ]
    then 
       pandoc -s temp.md -f markdown -t latex -o temp.pdf
       evince ~/temp.pdf & exit
    fi
    }

    Après avoir entré la commande man zsh dans un terminal, vous obtenez automatiquement ce document pdf : Zshzsh.pdf (83.35 Ko).

  • Python: La programmation parallèle avec le module threading

    Bonjour, 

    Aujourd'hui, j'ai envie de vous parler du module threading. Ce dernier gère la programmation parallèle dans le langage Python et il est fort utile. Je l'ai utilisé pour créer un bouton dont la finalité est d'afficher l'heure à la seconde près, et d'ouvrir un calendrier. Ce bouton a donc deux fonctions et pour remplir sa mission, il a besoin de deux boucles:

     

     Clockbutton2

             

    • une boucle qui surveille les événements de l'utilisateur. C'est la boucle mainloop() de l'environnement graphique tkinter. Par exemple, Si le pointeur de la souris survole le widget Button, la couleur de ce dernier change.
    • une boucle infinie de type while, qui tourne toutes les secondes et qui permet d'afficher l'heure exacte sur le bouton.

    Si nous ne lançons pas ces deux boucles en parallèle, alors soit le code affichera le défilement des secondes mais le bouton sera inactif, soit le bouton sera actif mais les secondes seront figées dans l'éternité... Enfin, jusqu'à l'arrêt forcé du programme.

    Voici un exemple de code qui ne fonctionne pas. Il y a dans ce code deux boucles : while 1 qui est une boucle infinie et mainloop() réceptionnaire d'événements du GUI tkinter. Lorsque le programme pénètre dans la boucle infinie, il n'a plus aucun moyen d'en sortir. Certes, il affichera le défilement des secondes jusqu'à la fin des temps, mais comme la boucle mainloop() se trouve en dehors, nous n'avons plus accès aux événements du bouton. Celui-ci est complètement pétrifié. Comme je l'explique plus bas dans la vidéo en lien avec ce billet, il n'est même pas possible de cliquer sur la croix pour fermer le programme.

    Si nous déplaçons la toute dernière instruction (button.mainloop) à l'intérieur de la boucle while, une seule seconde va défiler puis le programme va "sauter" dans la boucle mainloop() et quitter la boucle infinie. Nous aurons accès aux fonctionnalités du bouton mais l'heure restera figée.

    La solution

    Elle est fort simple. Voici le code qui fonctionne. Il suffit de créer deux objets de la classe threading et de les démarrer en parallèle presque simultanément grâce à la méthode start(). Celle-ci va ensuite passer le relais à la méthode self.run(). Les noms de ces deux méthodes sont génériques. Ils ne peuvent pas être remplacés par d'autres termes. Les deux processus ne démarrent pas exactement au même moment. Il y a une différence de 200 millièmes de secondes. Dans ce cas précis, cet intervalle est nécessaire si on ne veut pas que le programme se crashe lamentablement juste après le décollage.

    Une fois lancé, chaque "thread" vit sa vie. Ils ont toutefois la possibilité d'accéder à des instructions communes comme par exemple les variables de classe. C'est le cas dans mon programme. La boucle infinie a besoin de la variable qui stocke l'objet fenêtre principale. Mais pour éviter qu'ils se mélangent les pinceaux et qu'ils modifient au même moment des données vitales pour la stabilité du programme, nous importons la classe Lock() du module threading.

    Lock() signifie verrou. Je déclare donc une variable (lock = Lock()) en tout début de programme, et je verrouille le premier thread grâce à l'instruction with lock. Avec cet outil, le second thread ne ne démarrera que lorsque le premier aura terminé son travail et lui aura passé la main. En clair, le premier thread fait ce qu'il a à faire, tandis que le second qui n'est pas verrouillé, reste sur le seuil de la porte. Lorsque le premier est prêt, il ouvre la porte et laisse entrer le second thread. Si le premier doit reprendre son travail pour modifier je ne sais quel bouton, il prie le second de bien vouloir sortir de la pièce. C'est très pratique! Bien évidemment, comme le second thread est une boucle infinie, il n'est pas possible de le verrouiller. Il ne passerait jamais la main à son collègue. Voilà donc pour le module threading que je vous invite à découvrir. Si vous avez des remarques ou des interrogations, n'hésitez pas. Ma porte est ouverte.

     

  • Un environnement de bureau codé en Python

    1ère partie : la barre des tâches

     

    Taskbar3

    Bonjour,

    Il y a un peu plus d'un an, je m'étais lancé dans un projet ambitieux, en l'occurrence la programmation d'un environnement de bureau en langage Python. Le résultat n'avait pas été à la hauteur de mes espérances. Si j'ai réussi à coder le menu des applications, je n'ai jamais réussi à coder proprement la barre des tâches et le fond d'écran.

    Les boutons de la barre des tâches tremblotaient ou disparaissaient inopinément ce qui n'était pas un signe de stabilité. Mais ça, c'était avant. Aujourd'hui, je peux annoncer que j'ai réussi à coder une barre des tâches stable et fonctionnelle. Voici une petite vidéo pour illustrer mes propos:

     

     

    Vous trouverez le code sur mon dépôt git, à cette adresse.Le fichier qui lance l'application, se nomme miamondo.py. Il est mis à jour quotidiennement.

    Points à corriger ou à améliorer

    • Le placement des fenêtres. Lorsque l'une d'entre elles est maximisée et couvre les autres, je dois iconifier et désiconifier ces dernières pour les faire apparaitre au-dessus. Ce n'est pas satisfaisant.
    • Les icônes des boutons. J'ai prévu une icône par défaut, pour éviter de faire planter l'application. Mais cette icône apparait bien trop souvent à mon goût. Elle signifie que je n'ai pas réussi à automatiser mon système d'icônes de manière satisfaisante. La raison en est que je ne maîtrise pas suffisamment les expressions régulières (regex). Je dois donc travailler ce point en priorité. Les icônes sont toutes présentes dans mon système de fichiers Archlinux, soit sous /usr/share/icons ou bien sous /usr/share/pixmaps. Les applications sont toutes répertoriées sous /usr/share/applications. J'ai tout ce qu'il faut pour bien faire. Le problème vient donc de mes lacunes en regex.

    Points de satisfaction

    • Stabilité du code. Dans la barre des tâches, les boutons des applications ouvertes ne scintillent pas ou pire encore, ne disparaissent pas de manière inopinée. À l'ouverture d'une fenêtre, le bouton se matérialise immédiatement. À la fermeture de cette même fenêtre, le bouton qui lui est lié, disparait immédiatement de la barre des tâches. Cela prouve que les boucles fonctionnent. 
    • Découverte de la programmation parallèle avec le module threading.
    • Découverte et prise en compte de l'importance du module regex.
    • Le nombre de processus zombies ne dépasse pas 2, ce qui est le signe que le programme est plutôt bien codé, me semble-t-il.

    À bientôt pour la deuxième partie qui vous présentera le menu principal.

  • Un dé numérique codé en langage Python

    Cette après-midi, il ne faisait pas très beau. J'en ai donc profité pour coder une application que mon amie m'avait réclamée, en l'occcurrence un dé numérique. Bien évidemment, j'ai utilisé le langage Python et la bibliothèque Tkinter pour réaliser ce modeste projet. Rien de bien compliqué dans ce code qui comporte moins de 80 lignes. vous le trouverez ici sur mon dépot git. Le fichier lanceur se nomme dices.py.

    À noter l'utilisation du module random pour générer un nombre aléatoire à chaque fois que le dé est lancé. L'application comprend:

    • une fenêtre principale (tk.Tk),
    • un widget Frame (cadre),
    • un widget Label,
    • un widget Button (bouton).

    Ce code est sous licence libre. Vous pouvez donc vous l'approprier et l'améliorer. J'ai mis en ligne une vidéo Youtube qui vous donnera des explications plus détaillées.

     

  • Lucy, oméga de l'humanité

    La situation s’était dégradée très rapidement. L’été 2019 avait battu des records de chaleur et à partir de cette période, les canicules s’étaient enchaînées. En deux décennies à peine, la température moyenne avait grimpé de trois degrés provoquant une fonte des glaces et une montée des eaux qui avaient remodelé toutes les côtes de l’Europe. Les Pays-Bas avaient presque complètement disparu. Les côtes françaises ne cessaient de reculer face aux assauts d’un océan déchaîné par les tempêtes et des vents pouvant atteindre les 350 Km/h. Les feux de forêts avaient dévasté le Portugal tandis que l’Espagne s’était transformée en désert.

    La centrale nucléaire du Blayais fut abandonnée le 1er septembre 2039. Les réacteurs Blayais-2 et Blayais-4 explosèrent trois jours plus tard, contaminant une grande partie du califat mais également des zones situées en Europe Libre.

    Le front s’était stabilisé sur une ligne allant de Niort à Turin. Au Nord, l’Euroforce s’efforçait de contenir tant bien que mal les incursions des commandos du califat. Le bombardement atomique de Tripoli avait donné aux alliés un peu de répit sur le front Sud. Mais à l’Est, les Russes avançaient inexorablement et les Européens ne pouvaient plus compter sur l’aide des États-unis dont les structures fédérales s’étaient disloquées.

    Le monde sombrait dans la violence et le chaos. La situation était telle que le gouvernement chinois se résigna à déclencher l’opération Longue Marche, bien que celle-ci n'en était encore qu'au début du stade bêta. L’objectif était clair : Abandonner la Terre et transférer un maximum de citoyens vers les nouvelles colonies martiennes. Ces derniers avaient été sélectionnés selon des critères très stricts car ils devaient prendre part à la terraformation d’un nouveau monde et à la renaissance de la Chine. Toute la nation s’était lancée à corps perdu dans la production en grande série de vaisseaux de transport, exploitant à outrance les ressources que la planète-mère pouvait encore offrir. À quoi bon désormais prendre des précautions? Les décollages étaient quotidiens. Les vaisseaux étaient assemblés en orbite au prix de pertes humaines très importantes, tandis que les élus étaient acheminés dans l’espace interplanétaire, au-delà de la ligne de Kármán, par un ascenseur dont la construction s’était étalée sur dix ans.

    Ce n’est qu’après le dernier transfert en ascenseur et la fermeture du sas d’arrimage de l’ultime vaisseau d’évacuation, que la capsule, baptisée Volgor, fut larguée en direction de la surface de la Terre. Grâce à son bouclier thermique, elle survécut à la rentrée atmosphérique. Ses parachutes se déployèrent à une altitude de 3000 mètres et elle toucha délicatement le sol kazakh sous le regard intrigué de trois cavaliers des steppes. Ces derniers mirent pied à terre et restèrent un long moment immobiles, ne sachant quelle attitude adopter face à ce mystérieux objet tombé du ciel. 

    La capsule s’ouvrit comme une fleur qui déploie ses pétales. Ses dimensions étaient modestes. Elle ne faisait pas plus de cinquante centimètres de diamètre. Poussés par la curiosité, les cavaliers  s’approchèrent lentement. Elle était vide… Au bout de quelques minutes de palabres, l’un des trois hommes replia les pétales et plaça la capsule dans le sac qu’il portait en bandoulière. Ils regagnèrent leurs montures et quelques minutes plus tard, lancés au galop, ils disparurent au-delà de la ligne d’horizon. 

    Le dernier représentant de l’humanité sur la planète Terre mourut dans une horrible quinte de toux deux mois plus tard. C’était une femme, elle était africaine et elle s’appelait Lucy.