Live data from Hacker News

Designing command-line interfaces

antoarts.com

41–50 of 81 posts

Re: Designing command-line interfaces

#41
post #7

Oh, and another: Use your language's command-line option processing libraries. OptionParser in ruby and argparse in python. There is no reason to eschew these libraries: they're part of the standard library, they require zero coupling to your app logic, and they handle all of the edge cases for free. "But I can just shift the arguments", you say! Yeah? Great! What if the user pipes input through STDOUT? What if the u…

Just use the library. It's a solved problem!

Indeed! In fact it is so solved that the Python standard library has solved it differently 3-4 (I've lost count) times already, let alone the dozen or two extra packages at PyPI ;)

Re: Designing command-line interfaces

#42
post #3

Here's another one: Provide explicit flags for default behavior . For example, if your lines-of-code counting utility excludes preprocessor directives by default, and includes them when you pass "-i", provide an "-x" switch that signals to use the default behavior. This way, when someone wants to write a bash script that uses your utility, they can do this: case $include_directives in y) LOC_FLAGS='-i';; n) LOC_FLAGS…

What about the disadvantages? - It doubles the number of flags of the program. - It allows invalid or ambiguous combinations: is `myloc -i -x` valid? If yes which flag takes precedence? It seems these must outweigh the benefits or it wouldn't be so uncommon.

I've seen two conventions for conflicting flags: complain and bail out, or "last one wins" so in your example, -x.

Re: Designing command-line interfaces

#43
post #34

Non-interactive programs get the most attention in this article, while text-based user interfaces are barely covered at all. That's disappointing, I was hoping I'd learn how vi, etc. worked from this, since I know nothing about writing command line interfaces other than input and output to the last column of the last line of the terminal. Does anyone know of a good article/introduction to this?

Besides the technical details, there are good practices which should be followed, but I don't know of any document which lists them. This is a pity, because though text-based interfaces are often designed in a much more efficient way than GUI interfaces, they are seldom consistent between themselves, and often get something wrong. A few common ones: - Don't make the user reach for distant keys like escape or pagedown…

> For one-line text entry, support readline bindings (^W, ^U, ^Y, ^B, ^F, etc.)

Better yet, don't try to emulate readline--just use readline itself.

> spawn $PAGER to show text and $EDITOR to edit text.

If you're old school enough, honor $VISUAL and fall back to $EDITOR if it's not set.

Re: Designing command-line interfaces

#44
post #38
post #33

The name should be short. A long name will be tedious to type, so don’t call you version control program my-awesome-version-control-program. Call it something short, such as avc (Awesome Version Control). $ my-aw # yay! Personally, I am not a big fan of everyone using two or three-letter linux names for everything. We have a lot of options now for autocompletion and seeing what is available, so long names are no long…

$ may-aw my-awe-inspiring-tool my-awwwww-how-cute-program my-awesome-version-control-prog my-aww-yeah-tool my-awchoo-i-sneezed-program my-aw-long-your-names-are-grandma Also, please don't make me hit the - character when I call your program.

I prefer - over _ over smashingwordstogether. There are the benefits of readability and not needing to intermittently press the shift key. Also, you might prefer

    bind 'tab:menu-complete'

or to assign that to a different key. This allows you to quickly cycle through valid options so you are not playing "what's the next letter?" games.

Re: Designing command-line interfaces

#45
I'm glad he mentioned the "Silence trumps noise" point. I like to call the idiom "no news is good news". Tell me only when I need to know something (like a failure); "-v" is always there if I need it. It feels uncomfortable to get no output at first, but once you get used to it there's much less to read.

It's rather like the Plan 9 convention of programs returning strings instead of ints when then terminate; an empty string means success, a non-empty string contains the error message. I wish other OSes had adopted that.

Re: Designing command-line interfaces

#46
post #3

Here's another one: Provide explicit flags for default behavior . For example, if your lines-of-code counting utility excludes preprocessor directives by default, and includes them when you pass "-i", provide an "-x" switch that signals to use the default behavior. This way, when someone wants to write a bash script that uses your utility, they can do this: case $include_directives in y) LOC_FLAGS='-i';; n) LOC_FLAGS…

What about the disadvantages? - It doubles the number of flags of the program. - It allows invalid or ambiguous combinations: is `myloc -i -x` valid? If yes which flag takes precedence? It seems these must outweigh the benefits or it wouldn't be so uncommon.

Don't call it -i and -x, call it -i and --no-i or better, -i, --include and --no-include. Some getopts can provide this automatically.

Last flag wins is a common choice because it allows some script to contain yourcommand --include $@ and then you can override with --no-include.

Re: Designing command-line interfaces

#47

"GUIs also have the advantage when it comes to presenting and editing information that is by nature graphical. This includes photo manipulation and watching movies (I have always wanted a program that shows a movie in my terminal by converting it to ASCII art in real-time, that would be sweet)." This is an interesting discussion - what is the CLI, exactly? My personal PDF viewer is Zathura[1], which is controlled lik…

I have always wanted a program that shows a movie in my terminal by converting it to ASCII art in real-time, that would be sweet

For the benefit of the original author, mplayer and xine both have ASCII art output modes (mplayer -quiet -vo aa, aaxine).

Re: Designing command-line interfaces

#48
post #20

Do you really want to do this (y/n)? i would rather see this as Do you really want to do this (y/N)? capitalize the option that will be used by default if you hit enter with no other input.

I absolutely agree - and not only does the article barley scratch what is Unix standard anyways, and the more tricky questions such as piping, exit and error states, or the environment are left out. Kind of disappointing, in my opinion.

Re: Designing command-line interfaces

#49
This might not be shared by others, but here it goes.

If your CLI program is a file-format conversion utility, please include a way to dump meta-data, header formats, etc. Don't just silently convert from A to B, allow me to get at the info you have gathered from the input.

For example, a binary disassembler SHOULD dump the executable header format. An spreadsheet converter utility SHOULD display how many sheets there are, if there are macros, how many rows, etc.

One of my pet peeves is pdftotext, a very nifty utility that I use to convert PDF reports to ASCII for subsequent awking. pdftotext has an option to specify start and end pages to extract, but it doesn't have an -i or --info option that tells me how many pages a PDF file has. So, my scripts have a very high upper-limit, like 1000, and it converts the file page by page, until the output text page has a size of zero.

Which reminds me, I should probably fork the fucker this weekend, now that I have some free time.

Re: Designing command-line interfaces

#50
post #7

Oh, and another: Use your language's command-line option processing libraries. OptionParser in ruby and argparse in python. There is no reason to eschew these libraries: they're part of the standard library, they require zero coupling to your app logic, and they handle all of the edge cases for free. "But I can just shift the arguments", you say! Yeah? Great! What if the user pipes input through STDOUT? What if the u…

Just use the library. It's a solved problem! Indeed! In fact it is so solved that the Python standard library has solved it differently 3-4 (I've lost count) times already, let alone the dozen or two extra packages at PyPI ;)

Yeah most of my scripts use OptParse and I'm procrastinating the rewrite for newer versions of python. I think I may just use getopt, which isn't going anywhere, and roll my own extensions if I need them.
Post reply on HN