From 5772d366691bc4792f4e303539091f3bc43e8967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=CA=9C=C9=AA=E1=B4=8D=E1=B4=9C=CA=80=E1=B4=80=20Yu=CC=84?= Date: Sat, 22 Apr 2023 02:06:24 +0900 Subject: [PATCH 1/6] chore: update `authors` field in `Cargo.toml` (#41) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a22a602..79c056e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "fncmd" version = "1.3.1" license = "MPL-2.0" -authors = ["Yu Shimura "] +authors = ["Sʜɪᴍᴜʀᴀ Yū "] description = "Command line interface as a function." readme = "README.md" repository = "https://github.com/yuhr/fncmd" From 6713b08d052b43ff3aed00b1e43b1225f3a921ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=CA=9C=C9=AA=E1=B4=8D=E1=B4=9C=CA=80=E1=B4=80=20Yu=CC=84?= Date: Sat, 22 Apr 2023 03:10:04 +0900 Subject: [PATCH 2/6] build!: upgrade `clap` to 4.2.4 (#42) Upgraded from 3.0.7. It seems to be working without any changes to our macros, but by definition it may contain some breaking changes in the reexported stuff even we don't notice at this time, so we'd also mark this upgrade as a breaking change. --- Cargo.toml | 2 +- README.md | 23 ++++++++++----------- examples/example-basic/README.md | 28 ++++++++++---------------- examples/example-subcmds/README.md | 24 +++++++++------------- examples/example-subcmdsflat/README.md | 24 +++++++++------------- 5 files changed, 43 insertions(+), 58 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 79c056e..5335169 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,6 @@ doctest = false members = ["impl"] [dependencies] -clap = { version = "3.0.7", features = ["derive"] } +clap = { version = "4.2.4", features = ["derive"] } fncmd-impl = { path = "impl", version = "=1.3.1" } once_cell = "1.9.0" \ No newline at end of file diff --git a/README.md b/README.md index 9780db5..136d7b1 100644 --- a/README.md +++ b/README.md @@ -50,19 +50,18 @@ pub fn main( That's all, and now you got a command line program with options handled by `clap`. With above code, the help message will be like below: -```plaintext -crate-name 0.1.0 - +```console +$ crate-name --help Description of the command line tool -USAGE: - crate-name [OPTIONS] --foo +Usage: crate-name [OPTIONS] --foo + +Options: + -f, --foo Argument foo + -b, --bar Argument bar + -h, --help Print help + -V, --version Print version -OPTIONS: - -b, --bar Argument bar - -f, --foo Argument foo - -h, --help Print help information - -V, --version Print version information ``` The name and the version of your crate are automatically inferred from Cargo metadata. @@ -151,7 +150,7 @@ src Sometimes you may want to transform the `main` function with another attribute macro such as `#[tokio::main]` and `#[async_std::main]`. In such case you have to put `#[fncmd]` at the outmost level: -```rs +```rust /// Description of the command line tool #[fncmd] #[tokio::main] @@ -162,7 +161,7 @@ pub async fn main(hello: String) -> anyhow::Result<()> { But not: -```rs +```rust /// Description of the command line tool #[tokio::main] #[fncmd] diff --git a/examples/example-basic/README.md b/examples/example-basic/README.md index cc765c4..7aa19ec 100644 --- a/examples/example-basic/README.md +++ b/examples/example-basic/README.md @@ -1,32 +1,26 @@ ```console $ example-basic ? 2 -error: The following required arguments were not provided: - +error: the following required arguments were not provided: + -USAGE: - example-basic [OPTIONS] [NAME] +Usage: example-basic [NAME] -For more information try --help +For more information, try '--help'. ``` ```console $ example-basic --help -example-basic 0.0.0 -Prints greeting message +Description of the command line tool -USAGE: - example-basic [OPTIONS] [NAME] +Usage: crate-name [OPTIONS] --foo -ARGS: - Greeting message - Name of someone to greet - -OPTIONS: - --bang Whether to use “!” instead of “.” at the end of the message - -h, --help Print help information - -V, --version Print version information +Options: + -f, --foo Argument foo + -b, --bar Argument bar + -h, --help Print help + -V, --version Print version ``` diff --git a/examples/example-subcmds/README.md b/examples/example-subcmds/README.md index 58666c4..04fdc27 100644 --- a/examples/example-subcmds/README.md +++ b/examples/example-subcmds/README.md @@ -6,18 +6,15 @@ Top-level command is called. ```console $ example-subcmds --help -example-subcmds 0.0.0 +Usage: example-subcmds [COMMAND] -USAGE: - example-subcmds [SUBCOMMAND] +Commands: + child + help Print this message or the help of the given subcommand(s) -OPTIONS: - -h, --help Print help information - -V, --version Print version information - -SUBCOMMANDS: - child - help Print this message or the help of the given subcommand(s) +Options: + -h, --help Print help + -V, --version Print version ``` @@ -36,12 +33,11 @@ Two-level-deep subcommand is called. ```console $ example-subcmds orphan ? 2 -error: Found argument 'orphan' which wasn't expected, or isn't valid in this context +error: unrecognized subcommand 'orphan' -USAGE: - example-subcmds [SUBCOMMAND] +Usage: example-subcmds [COMMAND] -For more information try --help +For more information, try '--help'. ``` diff --git a/examples/example-subcmdsflat/README.md b/examples/example-subcmdsflat/README.md index bab9675..cd5d45a 100644 --- a/examples/example-subcmdsflat/README.md +++ b/examples/example-subcmdsflat/README.md @@ -6,18 +6,15 @@ Top-level command is called. ```console $ example-subcmdsflat --help -example-subcmdsflat 0.0.0 +Usage: example-subcmdsflat [COMMAND] -USAGE: - example-subcmdsflat [SUBCOMMAND] +Commands: + child + help Print this message or the help of the given subcommand(s) -OPTIONS: - -h, --help Print help information - -V, --version Print version information - -SUBCOMMANDS: - child - help Print this message or the help of the given subcommand(s) +Options: + -h, --help Print help + -V, --version Print version ``` @@ -36,12 +33,11 @@ Two-level-deep subcommand is called. ```console $ example-subcmdsflat orphan ? 2 -error: Found argument 'orphan' which wasn't expected, or isn't valid in this context +error: unrecognized subcommand 'orphan' -USAGE: - example-subcmdsflat [SUBCOMMAND] +Usage: example-subcmdsflat [COMMAND] -For more information try --help +For more information, try '--help'. ``` From 8bfe18a38e01380640789eb4394bb4d304dd6cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=CA=9C=C9=AA=E1=B4=8D=E1=B4=9C=CA=80=E1=B4=80=20Yu=CC=84?= Date: Sat, 22 Apr 2023 04:27:18 +0900 Subject: [PATCH 3/6] docs: update `README.md` (#43) --- README.md | 14 ++++++++++---- examples/README.md | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 examples/README.md diff --git a/README.md b/README.md index 136d7b1..66f5451 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@

Command line interface as a function.

fncmd

+```rust +#[fncmd::fncmd] pub fn main() { println!("Hello, World!"); } +``` + [![crates.io](https://img.shields.io/crates/v/fncmd)](https://crates.io/crates/fncmd) [![docs.rs](https://img.shields.io/docsrs/fncmd)](https://docs.rs/fncmd/latest/fncmd/) [![License](https://img.shields.io/github/license/yuhr/fncmd)](https://github.com/yuhr/fncmd/blob/develop/LICENSE) @@ -15,7 +19,7 @@ Imagine a command line program you want to create. Essentially, it can be abstracted as a simple function that takes command line options as arguments. Then there should be nothing to stop you from being able to write it *literally* as a function, without using structs or builders like today's Rustaceans do. -This concept is tremendously inspired by [`argopt`](https://crates.io/crates/argopt), I really appreciate the work. However, it still requires a bit of cumbersome code, especially for handling subcommands. `fncmd` has been rewritten from scratch to get rid of all the complexities. Let's dig into [Subcommands](#subcommands) section to see how we can handle it. +This concept is tremendously inspired by [`argopt`](https://crates.io/crates/argopt), I really appreciate the work. However, it still requires a bit of cumbersome code, especially for handling subcommands. `fncmd` has been rewritten from scratch to get rid of all the complexities. Dig into [Subcommands](#subcommands) section to see how we can handle it. ## Installation @@ -27,6 +31,8 @@ To install, run in your project directory: cargo add fncmd ``` +For those who prefer case studies: see [`examples`](./examples). + ## Basics This crate exposes just a single attribute macro, [`fncmd`], which can **only** be attached to the `main` function: @@ -64,9 +70,9 @@ Options: ``` -The name and the version of your crate are automatically inferred from Cargo metadata. +The name and the version of your command are automatically inferred from Cargo metadata. -The usage of the `opt` attribute is exactly the same as the [underlying `clap` attribute on arguments](https://github.com/clap-rs/clap#using-derive-macros), they're just passed as is, except that it appends `(long)` if no configuration was provided, i.e. `#[opt]` means `#[opt(long)]`. If you want to take the argument `foo` without `--foo`, just omit `#[opt]`. +The usage of the `opt` attribute is almost exactly the same as the underlying [`arg` attribute](https://docs.rs/clap/4.2.4/clap/_derive/index.html#arg-attributes). They're just passed as is, except that `(long)` is implied if no configuration was provided, i.e. `#[opt]` means `#[opt(long)]`. If you want to take the argument `foo` without `--foo`, just omit `#[opt]`. ## Subcommands @@ -131,7 +137,7 @@ another-orphan └── another-orphan sub ``` -Note that `another-orphan` is not contained within `another`, because it's not exposed as `pub`. As seen here, making the `main` of a target non-`pub` is only meaningful when you want it to have a common prefix with others but not to be included by another command, so in most cases you can set `pub` without thinking. +Note that `another-orphan` is not contained within `another`, because it's not exposed as `pub`. As seen here, making the `main` non-`pub` is only meaningful when you want it to have a common prefix with others but not to be included by another command, so in most cases you can set `pub` without thinking. Of course the same structure can be achieved without manually editing `Cargo.toml`, by placing files into the default location: diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..3ee3d1d --- /dev/null +++ b/examples/README.md @@ -0,0 +1 @@ +Each project `example-*` here is a standalone Cargo project to illustrate possible project setup. The `README.md` placed in the root of each project contains snapshot outputs of the built command(s) tested by [`trycmd`](https://crates.io/crates/trycmd), but at once it should be a good example to understand usage of `fncmd`. \ No newline at end of file From 59036aa906c396d5143b1935d6a587355c175658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=CA=9C=C9=AA=E1=B4=8D=E1=B4=9C=CA=80=E1=B4=80=20Yu=CC=84?= Date: Sat, 22 Apr 2023 04:38:21 +0900 Subject: [PATCH 4/6] test: fix snapshots (#45) --- examples/example-basic/README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/example-basic/README.md b/examples/example-basic/README.md index 7aa19ec..105df44 100644 --- a/examples/example-basic/README.md +++ b/examples/example-basic/README.md @@ -12,15 +12,18 @@ For more information, try '--help'. ```console $ example-basic --help -Description of the command line tool +Prints greeting message -Usage: crate-name [OPTIONS] --foo +Usage: example-basic [OPTIONS] [NAME] + +Arguments: + Greeting message + [NAME] Name of someone to greet Options: - -f, --foo Argument foo - -b, --bar Argument bar - -h, --help Print help - -V, --version Print version + --bang Whether to use “!” instead of “.” at the end of the message + -h, --help Print help + -V, --version Print version ``` From 92910a65622f5ded44863940ed037fde659d56ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=CA=9C=C9=AA=E1=B4=8D=E1=B4=9C=CA=80=E1=B4=80=20Yu=CC=84?= Date: Sat, 22 Apr 2023 04:41:00 +0900 Subject: [PATCH 5/6] test: fix test command to exclude invalid paths (#46) --- justfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/justfile b/justfile index 6df43ec..2f56b2c 100644 --- a/justfile +++ b/justfile @@ -6,8 +6,8 @@ setup: git config --local core.hooksPath .githooks test *ARGS: - for project in `ls examples`; do \ - RUST_BACKTRACE=1 cargo test --manifest-path examples/$project/Cargo.toml --workspace {{ARGS}} -- --nocapture; \ + for project in examples/example-*; do \ + RUST_BACKTRACE=1 cargo test --manifest-path $project/Cargo.toml --workspace {{ARGS}} -- --nocapture; \ done bump *ARGS: From c0a0d880a44dece764d377b7244ebc8163b5ae02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=CA=9C=C9=AA=E1=B4=8D=E1=B4=9C=CA=80=E1=B4=80=20Yu=CC=84?= Date: Sat, 22 Apr 2023 04:43:14 +0900 Subject: [PATCH 6/6] chore: bump version to 2.0.0 (#44) --- Cargo.toml | 4 ++-- impl/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5335169..59f3771 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fncmd" -version = "1.3.1" +version = "2.0.0" license = "MPL-2.0" authors = ["Sʜɪᴍᴜʀᴀ Yū "] description = "Command line interface as a function." @@ -19,5 +19,5 @@ members = ["impl"] [dependencies] clap = { version = "4.2.4", features = ["derive"] } -fncmd-impl = { path = "impl", version = "=1.3.1" } +fncmd-impl = { path = "impl", version = "=2.0.0" } once_cell = "1.9.0" \ No newline at end of file diff --git a/impl/Cargo.toml b/impl/Cargo.toml index 59c4dc9..20704a3 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fncmd-impl" -version = "1.3.1" +version = "2.0.0" license = "MPL-2.0" authors = ["Yu Shimura "] description = "This crate shouldn't be used directly. Check fncmd."