Jaka jest uważana najlepsza praktyka w zakresie używania / pomocy drukowania (--help)?

13

Kiedy piszę narzędzia do interfejsu CLI systemu UNIX, jak powinienem sprawić, aby program wydrukował pomoc i / lub użycie?

Zwykle używam fprintf(stderr, "help text here");, ale jest z tym kilka problemów.

  • Po pierwsze, nie jestem pewien, czy powinienem użyć stderr. Czy to w porządku, czy powinienem użyć stdout?
  • Jak możesz sobie wyobrazić, tekst pomocy jest dość długi, w zależności od liczby opcji dostępnych w narzędziu. Teraz zwykle umieszczam kilka "strings like that\n"w drugim parametrze. To jednak wypełnia mój kod źródłowy pięćdziesięcioma lub więcej liniami tekstu pomocy. To wcale nie jest łatwe do opanowania. Co powinienem zamiast tego zrobić?
  • Kiedy narzędzie nie jest napisane w języku C lub języku podobnym do C, zwykle używam tu-dokumentów tam, gdzie to możliwe (najlepiej w Perlu). Nie mogę tego użyć w C, ale czy jest coś takiego, czego mógłbym użyć?
  • Zastanawiałem się nad umieszczeniem go w headerfile.hśrodku #define HELP "help text here", nigdy nie widziałem go na wolności, nie wiem, czy powinienem go użyć.

Najlepiej byłoby umieścić tekst w zewnętrznym pliku i dołączyć go. Korzystanie #includez tego wydaje się jednak niewłaściwe. Więc co powinienem zrobić?

Chodzi o to, aby mieć tekst pomocy, który jest łatwy do zarządzania. Posiadanie go w kodzie źródłowym nie jest naprawdę wygodne.

polemon
źródło
1
Co jest tak złego w 50 liniach w kodzie źródłowym? Po prostu połóż to na końcu. To nie tak, że będziesz musiał regularnie z tym zadzierać.
whatsisname
2
Wykorzystanie @whatsisname, pomoc dla osób normalnych i długich. W końcu mam około 200 linii ciągów w kodzie źródłowym. Poza tym po prostu nie sądzę, że jest to najlepsza praktyka itp. Musi istnieć bardziej skuteczny sposób umieszczania tekstów pomocy itp.
polemon

Odpowiedzi:

8

Zainspiruj się elementami wewnętrznymi platformy docelowej

Zobacz kod źródłowy BSD. Oto na przykład:

  • usage(void)dla /usr/bin/unamenarzędzia NetBSD [ źródło ]:

    usage(void)
    {
        fprintf(stderr, "usage: uname [-amnprsv]\n");
        exit(EXIT_FAILURE);
    }
    
  • usage(void)dla NetBSD /usr/bin/telnet[ źródło ]

  • usage(void)dla OpenBSD /bin/ls[ źródło ]

Spójrz na alternatywy

I sam zdecyduj, czy są lepsze czy gorsze. Możesz użyć Google CodeSearch, aby znaleźć inne, takie jak:

Jak widać, inny styl między nimi a zintegrowanymi narzędziami systemów BSD wymienionymi powyżej. Nie oznacza to, że musisz podążać za jednym lub drugim. Ale zwykle dobrze jest rozejrzeć się i zadowolić spójnym rozwiązaniem.

Niestandardowe rozwiązanie do 50 linii pomocy ...

Jeśli nie lubisz unikać 50 wierszy tekstu, możesz po prostu przeczytać pomoc z pliku tekstowego (w postaci zwykłego tekstu lub bezpośrednio przeanalizować manźródło, jeśli je utworzyłeś). Uważam, że jest to dość elegancki sposób (ponieważ możesz nawet przejrzeć dokument tekstowy), jednak w przypadku podstawowych programów systemowych, które z natury sprawiłyby, że byłyby niebezpieczne i spowodowałyby błąd. Inni ludzie będą argumentować, że jest ciężki dla wiadomości usagelub helpwiadomości, ale to nie tak, że są one wywoływane w ciasnych pętlach ...

W razie wątpliwości podążaj za gigantami.

Haylem
źródło
9

Używam stdout, ponieważ pomoc nie jest błędem.

Jeśli jest to długa pomoc w C, staram się naśladować tutaj-docs:

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

Ale przez większość czasu piszę manstronę przy użyciu nroff -mandedykowanych tagów. Pomoc w aplikacji polega po prostu na odwoływaniu się do tej manstrony.

mouviciel
źródło
Ale pomoc niekoniecznie jest pożądana standardowa wydajność, prawda? Jak o stdlog?
greyfade,
@greyfade: Czy stdlogstandard C?
mouviciel
@mouviciel: ... Myślałem, że tak. Nie sądzę. C ++ posiada powiązany standardowy strumień ( cin, cout, cerr, i clog), więc myślę, że myślałem, że stdlogbył w standardzie C. Mój błąd.
greyfade,
2

Jeśli byłbym ci, że ja po prostu otworzył źródła grep, tail, cat, your_other_favorite_unix_shell_commandaby zobaczyć, jak to się robi tam. Jestem prawie pewien, że ich sposoby są dość dobrze przemyślane i mogą być utrzymywane przez wiele osób.

O stderrlub stdout. To naprawdę proste, jeśli wystąpi błąd - napisz do stderr, jeśli to tylko informacja - stdout. Na przykład, jeśli uruchomię twoje narzędzie z niewłaściwymi opcjami, możesz chcieć wyświetlić błąd, powiedzmy Use --help for usage, że ten należy do stderr. Jeśli uruchomię Twoje narzędzie z prawidłową opcją --help, użyj stdout.

Jeśli wolisz nie mieć długich ciągów pomocy w pobliżu swojego kodu, nie rób tego. #define w pliku nagłówkowym jest w porządku, ale tak naprawdę jest to osobista preferencja. Gdybym musiał odczytać kod narzędzia wiersza poleceń, wolałbym, aby jego ciąg pomocy znajdował się w pliku obsługującym opcje podane przez użytkownika.

devmiles.com
źródło
2
To nie odpowiada na jego pytanie.
Mavrik,
Hm, co jest z minusowaniem? Po co?
devmiles.com
@Mavrik: robi to pierwszy akapit.
haylem
1

Korzystam z biblioteki gnu getopts . Aby uzyskać przykład z pomocą, zobacz ten przykładowy projekt , w szczególności główną metodę na dole parser.y .

Ponieważ jest zawinięty w nawiasy klamrowe, używany przeze mnie edytor vim może złożyć razem linie i nawet ich nie zauważam, kiedy nie muszę.

Spencer Rathbun
źródło
1

Jeśli używam C lub wolę nie polegać na bibliotekach Boost, to trzymam się GNU getopt. W przeciwnym razie wolę Opcje programu doładowania, które automatycznie drukują pomoc.

Uważam również, że odgadnięcie odpowiedniej opcji jest jedną z najlepszych praktyk, jeśli chodzi o obsługę opcji. Nauczyłem się tego od Gita i teraz używam tego samego w moich projektach. Zasadniczo używa odległości Damerau – Levenshteina do drukowania najlepszych dopasowań, jeśli użytkownik wprowadzi nieznaną opcję wiersza poleceń.

Napisałem o tym mały artykuł , który możesz wykorzystać jako przykład.

Mam nadzieję, że to pomoże :)


źródło
1

Oczywiście pisanie strony dziury w kodzie cout << lub printf () jest kłopotliwe, szczególnie jeśli trzeba zmienić i ponownie wypełnić akapity. Dlatego oczywiście dobrym pomysłem jest edytowanie tego tekstu w osobnym pliku, na przykład za pomocą emacsa, w którym można łatwiej sformatować tekst.

Następnie możesz użyć następującego skryptu sed, aby przekonwertować ten plik tekstowy na legalny plik nagłówka C:

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

Następnie, po #include- wpisaniu pliku nagłówka do kodu źródłowego, możesz po prostu napisać tekst za pomocą

cout << helpStr;
użytkownik29809
źródło