Aide en ligne et help2man

Palaiseau, le dimanche 30 mai 2021

Cher Journal,

avec le temps, j'ai accumulé une petite collections de scripts et programmes divers, que je stocke dans un répertoire bin/ à la racine de mon répertoire home. Beaucoup d'entre eux sont simplement des lanceurs, afin de me faciliter le démarrage de programmes tiers ne faisant pas partie du système d'exploitation. Typiquement, ces lanceurs vont régler une ou deux variables d'environnement, éventuellement se placer dans le bon répertoire de travail, et enfin lancer un exec de la commande avec les bons arguments, suivant le schéma récurrent :

#! /bin/sh
set -e
cd /path/to/wd
VARIABLE1='value 1'
VARIABLE2='value 2'
export VARIABLE1 VARIABLE2
exec ./program argument1 argument2

Mais j'ai une autre catégorie de programmes dans mon répertoire bin/. Ce sont les utilitaires maison, qui me permettent d'automatiser des tâches afin de les lancer en une commande rapidement. L'un de mes utilitaires me permet de lancer une sauvegarde sur le bon disque branché à la machine, juste en tapant « backup ». Un autre utilitaire me permet de gérer mes schroots ; ce sont des sortes de conteneurs qui me permettent de conserver un environnement de compilation propre pour construire des paquets Debian.

Dans certains cas, je peux me retrouver à avoir plusieurs utilitaires avec des fonctions proches, auquel cas je peux me retrouver à les fusionner en un seul script. Toutefois, construire un programme avec de multiples fonctionnalités devient rapidement plus compliqué que d'avoir juste un script qui s'exécute de manière tout à fait séquentielle. Pour tout script ou programme, indépendamment du langage de programmation, ayant plus d'une fonctionnalité, je m'astreint à rédiger une fonction affichant juste un message d'aide, et une fonction additionnelle pour afficher le nom du programme et sa version. Le but de la manœuvre est de me permettre de me rappeler de comment utiliser mes propre commandes, notamment si je ne m'en sert qu'a une fréquence relativement faible. Cet exemple, tiré de mon script upgrade-schroots, montre que les information de programme et version arrivent en premier, directement suivies de la fonction affichant l'aide en ligne ; une copie complète du script est disponible en annexe :

#! /bin/sh
set -e
readonly PROGRAM="${0##*/}"
readonly VERSION="0.1.0"

print_usage () {
	cat <<-END
	Upgrade selectively schroots deployed on the machine.  If no schroot is
	specified, then a list of available schroots for upgrade is printed
	out.

	Usage: $PROGRAM [-adhlv] [schroots_names ...]

	Options:
	  -a, --all      upgrade all available schroots at once, instead of
	                 proceeding to upgrades on a selection of schroots.
	  -c, --check    check only that schroots listed in argument are part
	                 of the available ones.
	  -d, --debug    verbosely print out each command read and launched by
	                 the shell script, useful for debug.
	  -h, --help     print program usage information.
	  -l, --list     list all available schroots for upgrade.
	  -v, --version  print program version information.
	END
}

print_version () {
	echo "$PROGRAM $VERSION"
}

# [...]

Je place toujours mes fonction print_usage en tête du code source. Ça me permet de m'y référer rapidement quand je suis dans mon éditeur de texte. La sortie de la commande peut d'ailleurs sembler familière aux personnes habituées aux systèmes Unix.

$ upgrade-schroots --version
upgrade-schroots 0.1.0
$ upgrade-schroots --help
Upgrade selectively schroots deployed on the machine.  If no schroot is
specified, then a list of available schroots for upgrade is printed
out.

Usage: upgrade-schroots [-adhlv] [schroots_names ...]

Options:
  -a, --all      upgrade all available schroots at once, instead of
                 proceeding to upgrades on a selection of schroots.
  -c, --check    check only that schroots listed in argument are part
                 of the available ones.
  -d, --debug    verbosely print out each command read and launched by
                 the shell script, useful for debug.
  -h, --help     print program usage information.
  -l, --list     list all available schroots for upgrade.
  -v, --version  print program version information.

Le format familier est voulu, il est ajusté pour rendre proprement au format « page de manuel » après une passe de la commande GNU help2man(1), dans le cas présent, cela donnerait une page du genre :

$ help2man -N -LC.UTF-8 upgrade-schroots | man -l -
UPGRADE-SCHROOTS(1)      User Commands      UPGRADE-SCHROOTS(1)

NAME
       upgrade-schroots  -  manual  page  for  upgrade-schroots
       0.1.0

SYNOPSIS
       upgrade-schroots [-adhlv] [schroots_names ...]

DESCRIPTION
       Upgrade selectively schroots deployed  on  the  machine.
       If  no  schroot  is  specified, then a list of available
       schroots for upgrade is printed out.

OPTIONS
       -a, --all
              upgrade all available schroots at  once,  instead
              of  proceeding to upgrades on a selection of sch‐
              roots.

       -c, --check
              check only that schroots listed in  argument  are
              part of the available ones.

       -d, --debug
              verbosely   print   out  each  command  read  and
              launched by the shell script, useful for debug.

       -h, --help
              print program usage information.

       -l, --list
              list all available schroots for upgrade.

       -v, --version
              print program version information.

upgrade-schroots 0.1.0      May 2021        UPGRADE-SCHROOTS(1)

C'est une habitude que j'essaie de prendre. Des fois que je me retrouve à rédiger des programmes qui atterriraient dans Debian, fournir une page de manuel me serait nécessaire. Sauf que, à rédiger à la main, c'est un peu l'horreur, pour dire les choses poliment. Voici une version de la page ci-dessus sans passer par le lecteur de pages de manuel man :

.TH UPGRADE-SCHROOTS "1" "May 2021" "upgrade-schroots 0.1.0" "User Commands"
.SH NAME
upgrade-schroots \- manual page for upgrade-schroots 0.1.0
.SH SYNOPSIS
.B upgrade-schroots
[\fI\,-adhlv\/\fR] [\fI\,schroots_names \/\fR...]
.SH DESCRIPTION
Upgrade selectively schroots deployed on the machine.
If no schroot is specified,
then a list of available schroots for upgrade is printed out.
.SH OPTIONS
.TP
\fB\-a\fR, \fB\-\-all\fR
upgrade all available schroots at once,
instead of proceeding to upgrades on a selection of schroots.
.TP
\fB\-c\fR, \fB\-\-check\fR
check only that schroots listed in argument are part of the available ones.
.TP
\fB\-d\fR, \fB\-\-debug\fR
verbosely print out each command read and launched by the shell script,
useful for debug.
.TP
\fB\-h\fR, \fB\-\-help\fR
print program usage information.
.TP
\fB\-l\fR, \fB\-\-list\fR
list all available schroots for upgrade.
.TP
\fB\-v\fR, \fB\-\-version\fR
print program version information.
[ICO]NameLast modifiedSize
[PARENTDIR]Parent Directory  -
[   ]upgrade-schroots2021-05-30 18:09 3.2K

  —