Що вважається найкращою практикою використання друку / довідки (--help)?


13

Як писати інструменти для CLI UNIX, як мені зробити так, щоб програма роздрукувала довідку та / або використання?

Я зазвичай використовую fprintf(stderr, "help text here");, але з цим є кілька питань.

  • По-перше, я не впевнений, чи варто використовувати stderr. Це все в порядку, або я повинен використовувати stdout?
  • Як ви можете уявити, текст довідки досить довгий, залежно від того, скільки можливостей має інструмент. Зараз, як правило, я просто вкладаю кілька "strings like that\n"у другий параметр. Однак це заповнює мій вихідний код п'ятдесят і більше рядків довідкового тексту. Це зовсім не просто керовано. Що мені робити замість цього?
  • Коли інструмент не написаний на мові С або на C-подібній мові, я, як правило, використовую тут документи, де це можливо (найбільш чітко з Perl). Я не можу використовувати це в C, але чи є щось подібне, що я міг би використати?
  • Я розглядав питання про те, щоб помістити його headerfile.hвсередину #define HELP "help text here", я ніколи не бачив його в дикій природі, не знаю, чи слід реально це використовувати.

В ідеалі я міг би помістити текст у зовнішній файл і включити його. Використання #includeдля цього здається неправильним. Що мені робити тоді?

Ідея полягає у наявності довідкового тексту, який легко керується. Мати його всередині вихідного коду не дуже зручно.


1
Що так погано в 50-ти рядках у вихідному коді? Просто поставте його в кінці. Це не так, як вам доведеться регулярно возитися з цим.
whatsisname

2
@whatsisname використання, допомога для нормальних і довготривалих. У кінцевому підсумку у вихідному коді є близько 200 рядків рядків. Крім цього, я просто не вважаю, що це найкраща практика і т. Д. Має бути більш ефективним способом введення довідкових текстів тощо
полем

Відповіді:


8

Надихайтеся від внутрішніх цілей своєї цільової платформи

Погляньте на вихідний код BSD. Наприклад, ось:

  • usage(void)для /usr/bin/unameінструменту NetBSD [ джерело ]:

    usage(void)
    {
        fprintf(stderr, "usage: uname [-amnprsv]\n");
        exit(EXIT_FAILURE);
    }
    
  • usage(void)для /usr/bin/telnet[ джерело ] NetBSD

  • usage(void)для /bin/ls[ джерело ] OpenBSD

Погляньте на альтернативи

І вирішуйте самі, чи вони кращі, чи гірші. Ви можете використовувати Google CodeSearch для пошуку інших, наприклад:

Як бачите, різний стиль між цими та BSD системами інтегрований інструменти, перераховані вище. Це не означає, що вам потрібно слідувати за тим чи іншим. Але зазвичай добре озирнутися і домовитися про послідовне рішення.

Нестандартне рішення для 50 ліній допомоги ...

Якщо вам не подобається уникати 50 рядків тексту, ви можете просто прочитати довідку з текстового файлу (звичайним текстом або, можливо, безпосередньо проаналізувати manджерело, якщо ви створили його). Я вважаю, що це досить елегантний спосіб (як ви навіть можете шукати текстовий документ), однак для основних системних програм, які зробили б їх по суті небезпечними та ввели краху. Інші люди будуть стверджувати, що це важко для повідомлення usageчи helpповідомлення, але це не так, як їх називають у швидких щільних петлях ...

Коли сумніваєтесь, слідкуйте за гігантами.


9

Я використовую stdout, тому що допомога не є помилкою.

Якщо це велика допомога в С, я намагаюся імітувати сюди-документи:

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

Але більшу частину часу я пишу manсторінку, використовуючи nroff -manвиділені теги. Допомога в додатку просто полягає у переході на цю manсторінку.


Але допомога не обов'язково є бажаним стандартним результатом, чи не так? Як щодо stdlog?
greyfade

@greyfade: stdlogстандарт C?
mouviciel

@mouviciel: ... Я думав, що так і є. Я думаю, що не. C ++ має пов'язаний стандартний потік ( cin, cout, cerrі clog), так що я припускаю , що я думав , що stdlogбуло в стандарті C. Моє ліжко.
greyfade

2

Якщо я б тебе я просто відкрив джерела grep, tail, cat, your_other_favorite_unix_shell_commandщоб побачити , як це робиться там. Я впевнений, що їхні способи досить добре продумані, і їх може підтримувати багато людей.

Про stderrабо stdout. Це дуже просто, якщо є помилка - пишіть stderr, якщо це лише інформація - stdout. Наприклад, якщо я запускаю ваш інструмент з неправильними параметрами, можливо, ви захочете відобразити помилку, скажімо Use --help for usage, ця належить stderr. Якщо я запускаю ваш інструмент з допустимим варіантом --help, будь ласка, використовуйте stdout.

Якщо ви бажаєте не мати довгих рядків довідки біля коду, не варто. #define у ​​файлі заголовка - це прекрасно, але це дійсно особисті переваги. Якби мені довелося прочитати код інструменту командного рядка, я вважаю за краще, щоб його довідковий рядок знаходився у файлі, який обробляє параметри, надані користувачем.


2
Це не відповідає на його запитання.
Маврик

Гм, що з мінусом? Для чого?
devmiles.com

@Mavrik: перший абзац так і є.
хайлем

1

Я використовую бібліотеку gnu getopts . Для прикладу з допомогою дивіться цей зразок проекту , зокрема основний метод внизу parser.y .

Оскільки він загорнутий у фігурні дужки, редактор vim, який я використовую, може складати рядки разом, і я навіть не помічаю їх, коли мені цього не потрібно.


1

Якщо я використовую C або вважаю за краще не залежати від бібліотек Boost, я дотримуюся GNU getopt. Інакше я віддаю перевагу параметрам програми Boost, які друкують допомогу автоматично.

Я також вважаю відгадування правильного варіанту однією з найкращих практик, коли справа стосується обробки варіантів. Я дізнався це від Git і тепер використовую те саме у своїх проектах. В основному він використовує відстань Дамерау - Левенштайн для друку найкращих матчів, якщо користувач вводить якусь невідому опцію командного рядка.

Я написав про це невелику статтю , яку можна використовувати як приклад.

Сподіваюся, це допомагає :)


1

Очевидно, що написання діркової сторінки в cout << або printf () коді є громіздким, особливо якщо вам потрібно змінити і повторно заповнити ваші абзаци. Отже, очевидно, що корисно відредагувати цей текст в окремому файлі, використовуючи, наприклад, emacs, де можна простіше форматувати текст.

Тоді ви можете використовувати наступний скрипт sed для перетворення цього текстового файлу в законний файл заголовка C:

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

Потім, #include - додавши файл заголовка до вихідного коду, ви можете просто записати текст, використовуючи

cout << helpStr;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.