4 ms·
Context: maintainer of clap, a Cargo team member Regarding the CLI parser > This will take in our arguments (from something like std::env::args) and return ou
by epage 2y ago
Context: maintainer of clap, a Cargo team member
Regarding the CLI parser
> This will take in our arguments (from something like std::env::args) and return our matches, or an error.
`std::env::args` will panic on non-UTF8 content, like a file path. You could instead error on non-UTF8 content. Until recently, you had to pull in a dependency or reinvent some non-trivial stuff to properly deal with `OsStr`s. There are now `unsafe` functions for dealing with them. I'd like to extend things further to have a proper "pattern" API for `OsStr` which would allow almost everything a CLI parser needs to deal with `OsStr` without a dependency and without `unsafe`.
---
Regarding the discussion on dependencies, I think there are reasonable and valid situations to be careful of adding dependencies (see https://tweedegolf.nl/en/blog/119/sudo-rs-depencencies-when-less-is-better https://tweedegolf.nl/en/blog/119/sudo-rs-depencencies-when-... and the follow up https://www.reddit.com/r/rust/comments/1b92j0k/sudors_dependencies_when_less_is_better/ktuf2t2/ https://www.reddit.com/r/rust/comments/1b92j0k/sudors_depend...) but the reasoning here focuses on the wrong things imo.
> That would add 23 dependencies to my little project, if you count transitive dependencies. This can go up higher if you turn on a few features: derive, env, unicode, and wrap_help bring you up to 38 dependencies!
People overly focus on dependency counts. Yes, they mention dependency counts aren't a meaningful metric later but the lack of nuance here suggests they've not internalized that, including talking about the impact of optional dependencies when they advocate for optional dependencies later.
Clap can be trimmed down to just 4 dependencies. 1 of those exist for build performance. One might be able to be removed but is very light weight. The last is functionality that would exist either way, whether in its own crate or another.
> More concretely, by having no external dependencies you reduce your bug surface area. Sure, you own all the bugs now—but you won't get leftpad-ed, and you won't get dependabot alerts for third-removed transitive dependencies that now you've gotta patch.
crates.io is leftpad safe in all but the most extreme cases (law enforcement forces the deletion of a crate).
As I point out at the beginning, you already have a bug in this trivial code, one that is often hit when people think a CLI parser is trivial and they don't need dependencies.
> On the other hand, you miss out on nice things.
I think this is an understatement. imo one of the reasons we are seeing a lot of high quality CLIs out there is because its so easy to build on the work of others.
You also get very inconsistent results which makes the user experience much worse. Take the CLI parser shown here, it doesn't handle many conventions people expect, like multiple short flags (`-zxvf`). Having to deal with each CLI parser's quirks or only living with a subset of them all is not great.
> I think more things should be built from scratch and, ideally, without dependencies. You get to know the problem space better, and most things don't need the big sophisticated solution—but you pay for the whole dependency you pull in.
In creating a "product", the problem space of CLI parsing is not core. Same with a lot of what other dependencies provide. Instead of reinventing the wheel, you can better focus on the core of what you are trying to provide.
As for big sophisticated solutions, let's take the CLI space. There are many CLI parsers that you can pick from to adapt to the needs of your specific problem (https://github.com/rosetta-rs/argparse-rosetta-rs https://github.com/rosetta-rs/argparse-rosetta-rs) but do you want to go into discovery mode for every dependency for every project, pivot between them as requirements change, or deal with bouncing between APIs for non-core parts of your projects? I don't.
- oguz-ismail 2y ago>`std::env::args` will panic on non-UTF8 content, like a file path. Tell me this is a joke.
- namibj 2y agoWhat part do you hope/expect to be a joke there?
- Hemospectrum 2y agoThe documentation is quite clear on this point: > The returned iterator will panic during iteration if any argument to the process is not valid Unicode. If this is not desired, use the args_os function instead. std::env::args_os encodes paths as an OsString, which is allowed to contain invalid Unicode. You can then perform your own Unicode validation as needed, instead of the "ASAP" behavior of std::env::args. https://doc.rust-lang.org/std/env/fn.args.html https://doc.rust-lang.org/std/env/fn.args.html
- Analemma_ 2y agoI think this is fine? 99.99% of the time in application-land I want to be working with valid UTF-8 only, and an equal percentage of the time, filenames and CLI args cooperate. And as the sibling comments say, this is all well-documented. Frankly I think the onus should be on operating systems to get with the program and be UTF-8 everywhere (I think UCS-2 on Windows and "bag of bytes" filenames on Linux are braindead), but until that happens we at least have std::env::args_os as an escape hatch.
- Arch-TK 2y agoIf your program, especially if it accepts paths, flakes out over a path with a ISO/IEC 8859-1:1998 filename, it sucks. It's 2024, programs shouldn't be that unreliable. args_os is not an escape hatch, it's a pre-requisite to writing a command line argument parser. Honestly, I think the default args iterator should be deprecated, its functionality can be trivially rebuilt from args_os with the panic becoming more explicit.
- 2y ago