Quelle est la meilleure pratique pour l'utilisation / l'aide de l'impression (--help)?

13

Lors de l'écriture d'outils pour la CLI d'UNIX, comment dois-je faire pour que le programme imprime l'aide et / ou l'utilisation?

J'utilise habituellement fprintf(stderr, "help text here");, mais il y a plusieurs problèmes avec cela.

  • Tout d'abord, je ne sais pas si je devrais utiliser stderr. Est-ce correct ou dois-je utiliser stdout?
  • Comme vous pouvez l'imaginer, le texte d'aide est assez long, selon le nombre d'options de l'outil. Maintenant, j'ai l'habitude d'en mettre plusieurs "strings like that\n"dans le deuxième paramètre. Cependant, cela remplit mon code source de cinquante lignes ou plus de texte d'aide. Ce n'est pas facile à gérer du tout. Que dois-je faire à la place?
  • Lorsqu'un outil n'est pas écrit en C ou dans un langage de type C, j'ai tendance à utiliser ici-docs lorsque cela est possible (surtout avec Perl). Je ne peux pas utiliser ça en C, mais y a-t-il quelque chose comme ça, que je pourrais utiliser?
  • J'envisageais de le mettre dans un headerfile.hintérieur #define HELP "help text here", je ne l'ai jamais vu dans la nature, je ne sais pas si je devrais vraiment l'utiliser.

Idéalement, je pourrais mettre le texte dans un fichier externe et l'inclure. Utiliser #includepour cela semble cependant mal. Que dois-je faire alors?

L'idée est d'avoir un texte d'aide facilement gérable. L'avoir dans le code source n'est pas vraiment pratique.

polémon
la source
1
Qu'est-ce qui est si mauvais avec 50 lignes dans votre code source? Mettez-le à la fin. Ce n'est pas comme si vous deviez vous en occuper régulièrement.
whatsisname
2
Utilisation de @whatsisname, aide pour normal et longopts. Je finis par avoir environ 200 lignes de chaînes dans le code source. En dehors de cela, je ne pense pas que ce soit la meilleure pratique, etc. Il doit y avoir un moyen plus efficace de mettre des textes d'aide, etc.
polemon

Réponses:

8

Inspirez-vous des composants internes de votre plateforme cible

Jetez un œil au code source du BSD. Par exemple, voici:

  • usage(void)pour l' /usr/bin/unameoutil de NetBSD [ source ]:

    usage(void)
    {
        fprintf(stderr, "usage: uname [-amnprsv]\n");
        exit(EXIT_FAILURE);
    }
    
  • usage(void)pour NetBSD /usr/bin/telnet[ source ]

  • usage(void)pour OpenBSD /bin/ls[ source ]

Jetez un œil aux alternatives

Et décidez vous-même s'ils sont meilleurs ou pires. Vous pouvez utiliser Google CodeSearch pour en trouver d'autres, comme:

  • Utilisation de SkyLoad [ source ]

Comme vous pouvez le voir, style différent entre ceux-ci et les outils intégrés aux systèmes BSD répertoriés ci-dessus. Cela ne signifie pas que vous devez suivre l'un ou l'autre. Mais généralement, il est bon de regarder autour de soi et de se contenter d'une solution cohérente.

Une solution non standard aux 50 lignes d'aide ...

Si vous n'aimez pas éviter 50 lignes de texte, vous pouvez simplement lire l'aide d'un fichier texte (en texte brut, ou peut-être analyser directement la mansource du si vous en avez créé un). Je trouve que c'est une manière plutôt élégante (comme vous pouvez même rechercher le document texte), cependant pour les programmes de systèmes de base qui les rendraient intrinsèquement dangereux et introduiraient un point d'échec. D'autres personnes diront que c'est lourd pour un usageou un helpmessage, mais ce n'est pas comme si on les appelait en boucles serrées rapides ...

En cas de doute, suivez les géants.

haylem
la source
9

J'utilise stdout, car une aide n'est pas une erreur.

Si c'est une longue aide en C, j'essaie d'imiter ici-docs:

printf("This is the help for MyWonderfulApp\n"
       "Options are:\n"
       "    --help: display what you are reading now\n"
       "    --quiet: output nothing\n");

Mais la plupart du temps, j'écris une manpage à l'aide de nroff -manbalises dédiées. L'aide intégrée à l'application consiste simplement à se référer à cette manpage.

mouviciel
la source
Mais l'aide n'est pas nécessairement une sortie standard souhaitable, n'est-ce pas? Et alors stdlog?
greyfade
@greyfade: Est-ce la stdlognorme C?
mouviciel
@mouviciel: ... je le pensais. Je suppose que non. C ++ a un flux norme connexe ( cin, cout, cerret clog), donc je suppose que je pensais stdlogétait dans la norme C. Ma faute.
greyfade
2

Si je serais vous , je viens d' ouvrir des sources de grep, tail, cat, your_other_favorite_unix_shell_commandpour voir comment il est fait là - bas. Je suis sûr que leurs méthodes sont assez bien pensées et peuvent être entretenues par de nombreuses personnes.

À propos de stderrou stdout. C'est vraiment simple, s'il y a une erreur - écrivez à stderr, si c'est juste des informations - stdout. Par exemple, si j'exécute votre outil avec de mauvaises options, vous souhaiterez peut-être afficher une erreur, par exemple Use --help for usage, celle-ci appartient stderr. Si je lance votre outil avec une option valide --help, veuillez utiliser stdout.

Si vous préférez ne pas avoir de longues chaînes d'aide près de votre code, ne le faites pas. #define dans un fichier d'en-tête est parfaitement bien, mais c'est vraiment une préférence personnelle. Si je devais lire le code d'un outil de ligne de commande, je préférerais que sa chaîne d'aide soit dans un fichier qui gère les options fournies par l'utilisateur.

devmiles.com
la source
2
Cela ne répond pas à sa question.
Mavrik
Hm, qu'est-ce qui se passe avec le moins? Pourquoi?
devmiles.com
@Mavrik: le premier paragraphe le fait.
haylem
1

J'utilise la bibliothèque gnu getopts . Pour un exemple d'aide, consultez cet exemple de projet , en particulier la méthode principale au bas de parser.y .

Puisqu'il est entouré d'accolades, l'éditeur de vim que j'utilise peut plier les lignes ensemble, et je ne les remarque même pas quand je n'en ai pas besoin.

Spencer Rathbun
la source
1

Si j'utilise C ou préfère ne pas dépendre des bibliothèques Boost, je m'en tiens à GNU getopt. Sinon, je préfère les options du programme Boost qui impriment l'aide automatiquement.

Je considère également que deviner la bonne option est l'une des meilleures pratiques en matière de gestion des options. Je l'ai appris de Git et j'utilise maintenant la même chose dans mes projets. Il utilise essentiellement la distance Damerau – Levenshtein pour imprimer les meilleures correspondances si l'utilisateur entre une option de ligne de commande inconnue.

J'ai écrit un petit article à ce sujet que vous pouvez utiliser comme exemple.

J'espère que ça aide :)


la source
1

De toute évidence, écrire une page de trou dans le code cout << ou printf () est fastidieux, en particulier si vous devez modifier et remplir à nouveau vos paragraphes. Par conséquent, c'est évidemment une bonne idée de modifier ce texte dans un fichier séparé, en utilisant par exemple emacs où vous pouvez plus facilement formater votre texte.

Ensuite, vous pouvez utiliser le script sed suivant pour convertir ce fichier texte en un fichier d'en-tête C légal:

s/\"/\\\"/g
s/$/\\n"/
s/^/"/
1i\
const char *helpStr = 
$a\
;

Ensuite, lors de l' inclusion de votre fichier d'en-tête dans votre code source, vous pouvez simplement écrire votre texte en utilisant

cout << helpStr;
user29809
la source