rust-cli / book

Documentation on how to use the Rust Programming Language to develop commandline applications
https://rust-cli.github.io/book/index.html
MIT License
808 stars 106 forks source link

naming conventions for separating cli apps from libs #56

Open softprops opened 5 years ago

softprops commented 5 years ago

I was going to start a discussion on this on twitter https://twitter.com/softprops/status/1049729377699794944 but then I remembered this working group existed.

What I'm looking for is some guidance and direction for the current community standards ( if they exist ) around what to name my workspace members when I want to split a lib from cli app that is an interface for the lib. Ideally I'd be able to share the name for both but that's not possible with separate packages because their names are their unique identifiers!

killercup commented 5 years ago

Very good point! We should definintely add this to the book. Not sure where exactly; my first idea was to have the last chapter of the tutorial be "Growing your codebase".

Personally, I'd go for something like what I did with waltz (surprise!) but there are some alternatives. Here are some approaches I know of:

With the latter approach you can still have dependencies that only get included when you compile a certain binary. Or, actually, you can define that a certain binary will only get build if you enable some Cargo.toml features that also add some dependencies. This is what cargo-edit does.

killercup commented 5 years ago

Regarding naming conventions, a look at crates.io shows that (.+)[-_]cli$ is pretty popular. That may be biased on my searches, though. Notable exception: grep-cli is a library for building grep-like CLI applications (extracted from ripgrep).

To have the default main.rs be called foo instead of foo_cli, you'll have to do something like this however.

epage commented 5 years ago

Another relatively common one is -bin. Granted, I'm biased with cobalt-bin. (Never knew crates.io accepted regexes)

softprops commented 5 years ago

I went with lib/cli but now that bin was mentioned I kind of like that better.

Another question of convention is the package folders name of the crate. I just used the short form not knowing what a good convention was but kept standardish names in cargo.toml files.

In any case I'm happy to see a discussion around this happening.if anything shakes out around the convention I'd recommend porting the "rust book" workspace example to use it. That was my first introduction to cargo workspaces and likely the will be the first for others so it seems like a good opportunity for "teaching" a convention through first example.

killercup commented 5 years ago

Re cli vs bin: After thinking about this some more, I've actually come to like "-cli" more. A bin can be any crate that has ≥1 binary target. "CLI" is more specific in what these binaries are.

For example: Say I want to write a thing that converts the string "foo" to "bar". The library would be a crate "fooify", the CLI crate would be "fooify-cli", the web server with the fooify json API would be a "fooify-web" crate (that also contains one binary), the electron app that either wraps the library as Wasm or uses the server internally is "fooify-desktop", and last but not least the generic daemon that listens for files called foo and renames them is "fooifyd".

Except for maybe the electron one, the last few could also be "-bin"; and yes, they could in theory all be in the same crate, or even the same binary. But if you want to split them up, it makes sense to me be more specific than "bin".

On Wed, 10 Oct 2018, 03:09 doug tangren, notifications@github.com wrote:

I went with lib/cli https://github.com/softprops/emoji-clock?files=1 but now that bin was mentioned I kind of like that better.

Another question of convention is the package folders name of the crate. I just used the short form not knowing what a good convention was but kept standardish names in cargo.toml files.

In any case I'm happy to see a discussion around this happening.if anything shakes out around the convention I'd recommend porting the "rust book" workspace example to use it. That was my first introduction to cargo workspaces and likely the will be the first for others so it seems like a good opportunity for "teaching" a convention through first example.

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/rust-lang-nursery/cli-wg/issues/87#issuecomment-428403714, or mute the thread https://github.com/notifications/unsubscribe-auth/AABOX9SxJzzIfxDdbeYG5xc1Uq7qPg4Vks5ujUjKgaJpZM4XT5l5 .

killercup commented 5 years ago

From twitter thread: We should also have conventions around subcommands.

One last gotcha related to the naming of the workspace package. It affects the cargo install experience. cargo install emoji-clock-cli installs the emojiclock bin. I'm guessing this is where conventions will really come in handy to make this experience consistent for users
– @softprops

Ohhh I just noticed we should also probably talk about subcommands: Where foo-cli installs foo, foo-bar, and foo-baz (which can be called using "foo", "foo bar", and "foo baz")
– @killercup

dwijnand commented 5 years ago

:+1: for -cli. If you create a CLI-only tool, and later decide you'd rather it have a GTK interface instead, your users would probaby prefer if you retired your fooify-cli and recommending your new fooify-desktop rather than your fooify-bin suddenly having a completely different interface in a new version.

softprops commented 5 years ago

For the non cli/bin crate I'd like to claim a preference for keeping an unsuffixed/prefixed name. I've seen "foo-core" and "lib-foo" on the past. When I do imports I just want "use foo::Bar;"

epage commented 5 years ago

Agreed but to be clear, there are time for a -core crate but it should generally be a subordinate of a lib crate that re-exports it imo

An example is predicates where I wanted the traits kept separate so I could break compatibility more freely on predicates without disrupting the crates that use the traits in their API.

elasticdog commented 5 years ago

I like the "two crates in one repo that is a cargo workspace" pattern with -cli for the specificity that @killercup mentioned. It seems like subcommands could naturally fall under the the -cli crate with multiple binary targets?