Điều gì được coi là thực hành tốt nhất để sử dụng / trợ giúp in (- trợ giúp)?


12

Khi viết các công cụ cho CLI của UNIX, tôi nên làm thế nào để chương trình in ra trợ giúp và / hoặc sử dụng?

Tôi thường sử dụng fprintf(stderr, "help text here");, nhưng có một số vấn đề với điều đó.

  • Đầu tiên, tôi không chắc chắn, liệu tôi có nên sử dụng stderr. Điều đó có ổn không, hay tôi nên sử dụng stdout?
  • Như bạn có thể tưởng tượng, văn bản trợ giúp khá dài, tùy thuộc vào công cụ có bao nhiêu tùy chọn. Bây giờ, tôi thường, chỉ cần đặt một vài "strings like that\n"trong tham số thứ hai. Tuy nhiên, điều này sẽ lấp đầy mã nguồn của tôi bằng năm mươi dòng văn bản trợ giúp trở lên. Nó không dễ quản lý chút nào. Tôi nên làm gì thay thế?
  • Khi một công cụ không được viết bằng ngôn ngữ C hoặc ngôn ngữ giống như C, tôi có xu hướng sử dụng tài liệu ở đây nếu có thể (nổi bật nhất là với Perl). Tôi không thể sử dụng nó trong C, nhưng tôi có thể sử dụng cái gì đó không?
  • Tôi đang xem xét đưa nó vào headerfile.htrong #define HELP "help text here", tôi chưa bao giờ thấy nó trong tự nhiên, không biết liệu tôi có thực sự nên sử dụng nó không.

Lý tưởng nhất, tôi có thể đặt văn bản trong một tệp bên ngoài, và bao gồm nó. Sử dụng #includecho điều đó có vẻ sai, mặc dù. Tôi nên làm cái gì sau đó?

Ý tưởng là, để có một văn bản trợ giúp, có thể dễ dàng quản lý. Có nó bên trong mã nguồn không thực sự tiện lợi.


1
Điều gì quá tệ về 50 dòng trong mã nguồn của bạn? Chỉ cần đặt nó ở cuối. Nó không giống như bạn sẽ phải thường xuyên làm phiền nó.
whatsisname

2
@whatsisname sử dụng, giúp cho bình thường và longopts. Tôi cuối cùng có khoảng 200 dòng trong mã nguồn. Bên cạnh đó, tôi chỉ không nghĩ rằng đây là cách thực hành tốt nhất, v.v. Phải có cách đặt văn bản trợ giúp hiệu quả hơn, v.v.
Polemon

Câu trả lời:


8

Truyền cảm hứng cho bạn từ nội bộ của nền tảng mục tiêu của bạn

Hãy xem mã nguồn của BSD. Ví dụ, đây là:

  • usage(void)cho /usr/bin/unamecông cụ của NetBSD [ nguồn ]:

    usage(void)
    {
        fprintf(stderr, "usage: uname [-amnprsv]\n");
        exit(EXIT_FAILURE);
    }
    
  • usage(void)cho /usr/bin/telnet[ nguồn ] của NetBSD

  • usage(void)cho /bin/ls[ nguồn ] của OpenBSD

Có một cái nhìn vào các lựa chọn thay thế

Và tự quyết định xem họ tốt hơn hay xấu đi. Bạn có thể sử dụng Google CodeSearch để tìm người khác, như:

  • Cách sử dụng của SkyLoad [ nguồn ]

Như bạn có thể thấy, phong cách khác nhau giữa các công cụ này và các công cụ tích hợp hệ thống BSD được liệt kê ở trên. Điều đó không có nghĩa là bạn phải theo dõi cái này hay cái khác. Nhưng thường thì thật tốt khi nhìn xung quanh và giải quyết cho giải pháp nhất quán.

Một giải pháp không chuẩn cho 50 dòng trợ giúp ...

Nếu bạn không muốn tránh 50 dòng văn bản, bạn chỉ cần đọc trợ giúp từ tệp văn bản (bằng văn bản thuần túy hoặc có thể phân tích trực tiếp mannguồn của nguồn nếu bạn đã tạo). Tôi thấy rằng một cách khá tao nhã (thậm chí bạn có thể tra cứu tài liệu văn bản), tuy nhiên đối với các chương trình hệ thống cốt lõi sẽ khiến chúng không an toàn và gây ra lỗi. Những người khác sẽ tranh luận rằng nó nặng nề cho một tin nhắn usagehoặc helptin nhắn, nhưng nó không giống như những thứ này được gọi trong các vòng lặp nhanh ...

Khi nghi ngờ, hãy theo những người khổng lồ.


8

Tôi sử dụng stdout, bởi vì sự giúp đỡ không phải là một lỗi.

Nếu đây là một trợ giúp lâu dài trong C, tôi cố gắng bắt chước ở đây-docs:

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

Nhưng hầu hết thời gian tôi viết một mantrang bằng nroff -mancác thẻ chuyên dụng. Trợ giúp trong ứng dụng chỉ đơn giản bao gồm tham chiếu đến mantrang đó .


Nhưng sự giúp đỡ không nhất thiết là đầu ra tiêu chuẩn mong muốn, phải không? Thế còn stdlog?
greyfade

@greyfade: Là stdlogtiêu chuẩn C?
mouviciel

@mouviciel: ... Tôi nghĩ là vậy. Tôi đoán là không. C ++ có một dòng tiêu chuẩn có liên quan ( cin, cout, cerr, và clog), vì vậy tôi đoán tôi nghĩ stdloglà trong tiêu chuẩn C. Lỗi của tôi.
greyfade

2

Nếu tôi muốn được bạn tôi vừa mở lên nguồn grep, tail, cat, your_other_favorite_unix_shell_commandđể xem cách nó được thực hiện ở đó. Tôi khá chắc chắn rằng cách của họ được suy nghĩ khá tốt và có thể được nhiều người duy trì.

Giới thiệu stderrhay stdout. Nó thực sự đơn giản, nếu có lỗi - hãy viết thư stderr, nếu đó chỉ là thông tin - stdout. Ví dụ: nếu tôi chạy công cụ của bạn với các tùy chọn sai, bạn có thể muốn hiển thị một lỗi, giả sử Use --help for usage, công cụ này thuộc về stderr. Nếu tôi chạy công cụ của bạn với một tùy chọn hợp lệ --help, vui lòng sử dụng stdout.

Nếu đó là sở thích của bạn không có chuỗi trợ giúp dài gần mã của bạn, thì không. #define trong tệp tiêu đề là hoàn toàn tốt, nhưng đó thực sự là một sở thích cá nhân. Nếu tôi phải đọc mã của một công cụ dòng lệnh, tôi thích chuỗi trợ giúp của nó nằm trong một tệp xử lý các tùy chọn do người dùng cung cấp.


2
Điều đó không trả lời câu hỏi của anh ấy.
Mavrik

Hừm, có chuyện gì thế? Để làm gì?
devmiles.com

@Mavrik: đoạn đầu tiên nào.
haylem

1

Tôi sử dụng thư viện gnu getopts . Để biết ví dụ với trợ giúp, hãy xem dự án mẫu này , cụ thể là phương thức chính ở dưới cùng của Parser.y .

Vì nó được bọc trong các dấu ngoặc nhọn, trình soạn thảo vim tôi sử dụng có thể gấp các đường lại với nhau và tôi thậm chí không nhận thấy chúng khi tôi không cần.


1

Nếu tôi sử dụng C hoặc không muốn phụ thuộc vào các thư viện Boost, thì tôi sẽ sử dụng GNU getopt. Nếu không, tôi thích Tùy chọn chương trình Boost sẽ in tự động.

Tôi cũng xem xét việc đoán đúng lựa chọn một trong những thực tiễn tốt nhất khi xử lý các tùy chọn. Tôi đã học nó từ Git và bây giờ sử dụng tương tự trong các dự án của tôi. Về cơ bản, nó sử dụng khoảng cách Damensau của Levenshtein để in các trận đấu tốt nhất nếu người dùng nhập một số tùy chọn dòng lệnh không xác định.

Tôi đã viết một bài viết nhỏ về điều này mà bạn có thể sử dụng làm ví dụ.

Hy vọng nó giúp :)


1

Rõ ràng, viết một trang lỗ trong mã cout << hoặc printf () rất cồng kềnh, đặc biệt nếu bạn cần thay đổi và điền lại các đoạn văn của mình. Do đó, rõ ràng là một ý tưởng tốt để chỉnh sửa văn bản đó trong một tệp riêng biệt, sử dụng ví dụ emacs nơi bạn có thể dễ dàng định dạng văn bản của mình hơn.

Sau đó, bạn có thể sử dụng tập lệnh sed sau đây để chuyển đổi tệp văn bản đó thành tệp tiêu đề C hợp pháp:

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

Sau đó, khi #include -ing tập tin tiêu đề của bạn vào mã nguồn của bạn, bạn có thể chỉ đơn giản là viết ra văn bản bằng cách sử dụng

cout << helpStr;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.