rust-cli / team

CLI working group
https://rust-cli.github.io/book
MIT License
295 stars 34 forks source link

Support development of well-behaved CLI apps #21

Open jonblack opened 6 years ago

jonblack commented 6 years ago

CLI applications are expected to behave in a certain way. This is especially important when those applications are used in scripts.

I can always add more from the comments.

epage commented 6 years ago

Someone else brought up consistency in command line flags. These resources might be useful

BurntSushi commented 6 years ago

Another to add to the list:

killercup commented 6 years ago

Thanks for opening this! One of the goals of this WG should be to have a best-pratice list like this including source code example in Rust :)

uazu commented 6 years ago

Another suggestion:

The intention is to allow the log-files to be viewed sensibly in a pager or when converted to HTML in a browser.

killercup commented 6 years ago

More advanced/obscure:

lzybkr commented 6 years ago

@killercup - I think structured output will not be obscure in the future.

PowerShell has demonstrated the usefulness of structured output, but that usefulness quickly disappears stepping outside of PowerShell's cmdlets and scripts.

CLI tools are using language specific frameworks more and more which helps a lot with offering UI benefits like common command line parsing, generating command completions. I really hope structured output is one of these future benefits.

ripgrep --vimgrep is one immediate non-shell example where structured output is super useful, I envision a future where there are multiple shells other than PowerShell that would benefit from structured output as well.

kbknapp commented 6 years ago

I have the start of the "book" (I use that term loosely) I started which was meant to going over these exact points. CLI consistency is something I'm very interested in and would like to work on.

If I get some spare time, perhaps I can start this back up and open it up to the community for edits.

The book started as a clap reference, but the more I've thought about it I what I really want to do is sections that are more parser agnostic and goes over building command line applications and best practices such as the ones listed above.

Ultimately I'd like the book to be broken up into three parts:

jonblack commented 6 years ago

@kbknapp I like the proposed layout for the book and would love to help out. A lot of what's being proposed I suspect will end up in the first section since they are guidelines. I also think some of these behaviors are optional (e.g. structured output) while others should be politely enforced (e.g. exit status, graceful exit, ansi colors) with a crate or two.

jonblack commented 6 years ago

I found the following quotes about the UNIX philosophy which I think outline our cause, too:

Many UNIX programs do quite trivial things in isolation, but, combined with other programs, become general and useful tools. - Brian Kernighan, 1984

This is the UNIX philosophy: write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface. - Doug McIllroy, 1978

jonblack commented 6 years ago

I copied the following items from the here: https://www.slideshare.net/bigfishdesign/well-behaved-unix:

kalefranz commented 6 years ago

I’m a rust n00b, coming from python. So could be a non-issue for rust, but w.r.t. signal handling... a tricky part seems to be correctly passing those signals to subprocesses. Basically making sure users ultimately get the expected behavior from a sent signal even if the primary process has happened to fork a subprocess or three.

XAMPPRocky commented 6 years ago

For some of items mentioned at the top could a utility be built that lints against binaries in general? For example you give it a list of commands, ones that should succeed & fail and check against the status code, read the —help format check that each short option has a long option equivalent, etc.

Screwtapello commented 6 years ago

For more potential suggestions about "well-behaved CLI apps", you could look at the GNU Coding Standards. Highlights include:

There's a bunch of other guidance too, some of it more or less specific to GNU projects and/or C projects.

I can't find an equivalent document for OpenBSD or FreeBSD, except that style(9) mentions "Usage statements should look like the manual page's SYNOPSIS."

luser commented 6 years ago

Likewise, please don’t make the behavior of a command-line program depend on the type of output device it gets as standard output or standard input. Device independence is an important principle of the system’s design; do not compromise it merely to save someone from typing an option now and then.

As a counterpoint, I do think detecting a terminal for automatic color output is sensible and widely adopted.

I don't love the GNU standards, but there are certainly some good things in there. Supporting --help and --version has become widely accepted, for example.

epage commented 6 years ago

Should we include any guidance on line endings?

With cobalt, we had some tests failing when developers were using autocrlf because of some odd behaviors. in cobalt cobalt was inconsistent on line endings e.g. if you used markdown, then the line endings would be normalized. We ended up just giving up and calling normalize_line_endings on everything.

Screwtapello commented 6 years ago

As a counterpoint, I do think detecting a terminal for automatic color output is sensible and widely adopted.

Yeah, at this point I'd be surprised and a little annoyed if a program didn't turn off colour output when piped to another command.

I think that particular guideline is aimed at tools like ripgrep that produce output in a different syntax, not just uncoloured, when the output is a terminal. I remember trying to write a shell-script to do something useful with ripgrep output once; I ran ripgrep once to see what the output looked like, I wrote my script to manage that output, then I piped ripgrep's output into my script and everything fell apart. I certainly understand why ripgrep does that (it tries to produce more machine-readable output when it thinks it's talking to a machine), but I'd probably rather it print the same format but log a warning to stderr like "You seem to be piping ripgrep output to another program; you can use the --vimgrep option to produce output that's easier to parse, or --quiet to silence this hint".

Should we include any guidance on line endings?

You mean in program output, or what line-endings programs should support in input files?

epage commented 6 years ago

You mean in program output, or what line-endings programs should support in input files?

The one that I was thinking of was output but probably good to document input as well.

uazu commented 6 years ago

Yeah, at this point I'd be surprised and a little annoyed if a program didn't turn off colour output when piped to another command.

But then again 'less' can handle colour output (with -R), so I'd want an option to turn it back on again for piping to less. With ripgrep I have a wrapper script which sets it all up as I want it.

tomwhoiscontrary commented 6 years ago

On signals, can i suggest handling SIGWINCH? You can get that when the user resizes the terminal you're running in. The right behaviour might be to do nothing, or to redraw if it's a curses-style interface. It's almost certainly not to crash, which is something i have seen!

uazu commented 6 years ago

When SIGWINCH is used, wouldn't it normally be handled by the curses-like layer? That's how I've coded it in the past. So normal app code wouldn't need to touch it. It is something specific to library code in just a few places. Anyway, perhaps you could add a note to #27.

XAMPPRocky commented 6 years ago

While curses/TUI's aren't covered by the WG I would like to see some way of having responsive cli output for humans as currently to be the most compatible you have to print at 80 columns. For example if you're printing a table it'd be nice to be set a minimum and maximum column width with shortening or line breaking a column. Also on SIGWINCH specifically it'd be nice for loading bars to be respond to terminal width changes than break completely on any width change.