Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: propagate doc comments on flags and arguments to --help/-h + structs derive refactor #26

Open
wants to merge 60 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
251dfce
commented: add propagate doc attributes for clap's derive of `help` a…
Dec 11, 2024
ae76568
test: add test_doc_comments_propagate
Dec 12, 2024
0c3ce3a
uncomment: propagating doc comments attributes
Dec 12, 2024
e02529d
chore: add dbg_cond! macro
Dec 12, 2024
912744d
chore: add passthrough of `verbatim_doc_comment` attribute to clap
Dec 12, 2024
1d16e9b
merge: master into this
Jan 6, 2025
451e7e3
ci: fix clippy
Jan 6, 2025
d1d8e06
Merge branch 'master' into propagate_doc_comments_on_flags
Jan 7, 2025
7ef647b
Merge branch 'master' into propagate_doc_comments_on_flags
Jan 7, 2025
19c9d77
test: add 2 simple tests for enums
Jan 7, 2025
15bc985
test: add `strum_discriminants(strum` attributes to enum test
Jan 7, 2025
9de4082
test: add doc comment over enum for test with strum-messages
Jan 7, 2025
e28aee7
doc: check nice publish with private items
Jan 7, 2025
b831cbc
doc: add doc-string about dbg_cond! macro
Jan 7, 2025
1344f02
ci: resolve #34
Jan 9, 2025
222ee83
chore: add rust-toolchain.toml (autoinstalls rust-analyzer for any co…
Jan 9, 2025
709e4bc
chore: extract logic to derives::interactive_clap::structs::cli_varia…
Jan 9, 2025
13e6f2a
chore: move derives::interactive_clap::methods::cli_field_type module…
Jan 9, 2025
63dea02
chore: change `field_type` return type from TokenStream -> syn::Type
Jan 9, 2025
18ae13e
chore: group together derive items, that belong to `structs::cli_vari…
Jan 9, 2025
99d1c65
chore: move `impl From<#name> for #cli_name` derive into submodule
Jan 9, 2025
4d84f7c
chore: move impl #name (clap::Parser adapter block) into submodule
Jan 9, 2025
96072dc
chore: extract from_cli_for_struct module
Jan 24, 2025
0e9dc32
chore: extract stucts::input_args_impl module
Jan 24, 2025
f922cda
chore: move fields_with_subcommand to structs::common_methods
Jan 24, 2025
53551bf
chore: move fields_with_subargs to structs::common_methods
Jan 24, 2025
8d6750d
chore: move skip_interactive_input to structs::common_methods
Jan 24, 2025
086d39f
chore: extract to_interactive_clap_context_scope_trait module
Jan 24, 2025
77604e2
test: add test for named_arg attribute
Jan 24, 2025
060f38c
chore: extract clap_enum_for_named_arg module
Jan 24, 2025
1db0c12
chore: overall structs derive layout established
Jan 24, 2025
6bc7672
chore: tidy + clippy
Jan 24, 2025
48f96f6
test: add bug_fix_to_cli_args test
Feb 3, 2025
19b2099
test: change order of fragments in test_bug_fix_of_to_cli_args_derive…
Feb 3, 2025
29c9aea
test: add doc comment to intermediate struct field, which causes ToCl…
Feb 3, 2025
c66953e
fix: bug with to_cli_args command printing
Feb 3, 2025
424cef0
test: ignore snapshots for test_simple_struct
Feb 4, 2025
e9e96ab
test: forwardport test+snapshots for test_simple_struct from `master`
Feb 4, 2025
eb4b124
testcode + snapshot change of master -> (pr) for `test_simple_struct`
Feb 4, 2025
7c296a4
test: add context for why test_bug_fix_of_to_cli_args_derive was added
Feb 4, 2025
65f6fb7
test: ignore snapshots for test_simple_struct_with_named_arg
Feb 4, 2025
ccfbb2c
test: forwardport test+snapshots for test_simple_struct_with_named_ar…
Feb 4, 2025
ddb3891
testcode + snapshot change of master -> (pr) for `test_simple_struct_…
Feb 4, 2025
632ac61
test: ignore test+snapshots for test_doc_comments_propagate
Feb 4, 2025
26ee82d
test: forwardport test+snapshots for test_doc_comments_propagate from…
Feb 4, 2025
6461299
testcode + snapshot change of master -> (pr) for `test_doc_comments_p…
Feb 4, 2025
840636a
test: ignore test+snapshots for test_simple_enum
Feb 4, 2025
5dc36c1
test: forwardport test+snapshots for test_simple_enum from `master`
Feb 4, 2025
7e1ec80
test: ignore test+snapshots for test_simple_enum_with_strum_discrimin…
Feb 4, 2025
d87ee59
test: forwardport test+snapshots for test_simple_enum_with_strum_disc…
Feb 4, 2025
985a465
test: unify 2-step variables names in derive tests
Feb 5, 2025
382cc33
chore: extract cli_variant_struct derive module for reusability in tests
Feb 5, 2025
3db17e1
test: add to_cli_args_structs_test_bridge module for automatic step i…
Feb 5, 2025
f85e437
suggestion ui: Update src/lib.rs
dj8yfo Feb 10, 2025
87848e4
review: addresses https://github.com/near-cli-rs/interactive-clap/pul…
Feb 10, 2025
bc0a363
review: silence a clippy lint too https://github.com/near-cli-rs/inte…
Feb 10, 2025
aad7bda
review: resolves (1) https://github.com/near-cli-rs/interactive-clap/…
Feb 10, 2025
9bedd97
review: addresses https://github.com/near-cli-rs/interactive-clap/pul…
Feb 10, 2025
804e120
review: addresses https://github.com/near-cli-rs/interactive-clap/pul…
Feb 10, 2025
c9cce06
review: addresses https://github.com/near-cli-rs/interactive-clap/pul…
Feb 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,23 @@ jobs:
profile: minimal
- name: Tests
run: cargo test --workspace
# there're sometimes warnings, which signal, that the generated doc
# won't look as expected, when rendered, and sometimes errors, which will prevent doc from being
# generated at release time altogether.
cargo-doc:
runs-on: ubuntu-20.04

steps:
- uses: actions/checkout@v4
- name: Install Toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
default: true
- name: run cargo doc
env:
RUSTDOCFLAGS: -D warnings
run: |
cargo doc -p interactive-clap
cargo doc -p interactive-clap-derive --document-private-items
5 changes: 5 additions & 0 deletions examples/struct_with_subargs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ use interactive_clap::{ResultFromCli, ToCliArgs};
#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
struct Account {
/// Change SocialDb prefix
///
/// It's a paraghraph, describing, this argument usage in more detail
/// than just the headline
#[interactive_clap(long)]
#[interactive_clap(skip_interactive_input)]
#[interactive_clap(verbatim_doc_comment)]
dj8yfo marked this conversation as resolved.
Show resolved Hide resolved
social_db_folder: Option<String>,
/// Sender account
#[interactive_clap(subargs)]
account: Sender,
}
Expand Down
8 changes: 8 additions & 0 deletions interactive-clap-derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ syn = "1"
prettyplease = "0.1"
insta = "1"
syn = { version = "1", features = ["full"] }

[package.metadata.docs.rs]
# Additional `RUSTDOCFLAGS` to set (default: [])
rustdoc-args = ["--document-private-items"]

[features]
default = []
introspect = []
27 changes: 27 additions & 0 deletions interactive-clap-derive/docs/clap_enum_for_named_arg_docstring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
derive of helper enum for structs with `#[interactive_clap(named_arg)]` on fields
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's internal doc, so I would better keep it with the code at the level with the code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assumed this to be the duplicate of #26 (comment)



```rust,ignore
struct #name {
#[interactive_clap(named_arg)]
///Specify a sender
field_name: Sender,
}
```

gets transformed
=>

```rust,ignore
#[derive(Debug, Clone, clap::Parser, interactive_clap_derive::ToCliArgs)]
pub enum ClapNamedArgSenderFor#name {
///Specify a sender
FieldName(<Sender as interactive_clap::ToCli>::CliVariant),
}
impl From<Sender> for ClapNamedArgSenderFor#name {
fn from(item: Sender) -> Self {
Self::FieldName(<Sender as interactive_clap::ToCli>::CliVariant::from(item))
}
}
```

70 changes: 70 additions & 0 deletions interactive-clap-derive/docs/structs_from_cli_trait_docstring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
`interactive_clap::FromCli` derive

This modules describes derive of `interactive_clap::FromCli` trait for `#name` struct,
which happens during derive of [`crate::InteractiveClap`] for `#name` struct:

The implementation combines usages of all of [super::structs::to_cli_trait], [super::structs::input_args_impl],
[super::structs::to_interactive_clap_context_scope_trait]


derive input `#name`

```rust,ignore
struct #name {
age: u64,
first_name: String,
}
```

gets transformed
=>

```rust,ignore
impl interactive_clap::FromCli for #name {
type FromCliContext = ();
type FromCliError = color_eyre::eyre::Error;
fn from_cli(
optional_clap_variant: Option<<Self as interactive_clap::ToCli>::CliVariant>,
context: Self::FromCliContext,
) -> interactive_clap::ResultFromCli<
<Self as interactive_clap::ToCli>::CliVariant,
Self::FromCliError,
>
where
Self: Sized + interactive_clap::ToCli,
{
let mut clap_variant = optional_clap_variant.clone().unwrap_or_default();
if clap_variant.age.is_none() {
clap_variant
.age = match Self::input_age(&context) {
Ok(Some(age)) => Some(age),
Ok(None) => {
return interactive_clap::ResultFromCli::Cancel(Some(clap_variant));
}
Err(err) => {
return interactive_clap::ResultFromCli::Err(Some(clap_variant), err);
}
};
}
let age = clap_variant.age.clone().expect("Unexpected error");
if clap_variant.first_name.is_none() {
clap_variant
.first_name = match Self::input_first_name(&context) {
Ok(Some(first_name)) => Some(first_name),
Ok(None) => {
return interactive_clap::ResultFromCli::Cancel(Some(clap_variant));
}
Err(err) => {
return interactive_clap::ResultFromCli::Err(Some(clap_variant), err);
}
};
}
let first_name = clap_variant.first_name.clone().expect("Unexpected error");
let new_context_scope = InteractiveClapContextScopeFor#name {
age: age.into(),
first_name: first_name.into(),
};
interactive_clap::ResultFromCli::Ok(clap_variant)
}
}
```
44 changes: 44 additions & 0 deletions interactive-clap-derive/docs/structs_input_args_impl_docstring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
per-field input with [inquire::CustomType](https://docs.rs/inquire/0.6.2/inquire/struct.CustomType.html) impl block

This modules describes derive of input args implementation block for `#name` struct,
which contains functions `input_#field_ident` per each field,
which prompt for value of each field via [inquire::CustomType](https://docs.rs/inquire/0.6.2/inquire/struct.CustomType.html)
, which happens during derive of [`crate::InteractiveClap`] for `#name` struct:

derive input `#name`

```rust,ignore
struct #name {
age: u64,
first_name: String,
}
```


gets transformed
=>

```rust,ignore
impl #name {
fn input_age(_context: &()) -> color_eyre::eyre::Result<Option<u64>> {
match inquire::CustomType::new("age").prompt() {
Ok(value) => Ok(Some(value)),
Err(
inquire::error::InquireError::OperationCanceled
| inquire::error::InquireError::OperationInterrupted,
) => Ok(None),
Err(err) => Err(err.into()),
}
}
fn input_first_name(_context: &()) -> color_eyre::eyre::Result<Option<String>> {
match inquire::CustomType::new("first_name").prompt() {
Ok(value) => Ok(Some(value)),
Err(
inquire::error::InquireError::OperationCanceled
| inquire::error::InquireError::OperationInterrupted,
) => Ok(None),
Err(err) => Err(err.into()),
}
}
}
```
54 changes: 54 additions & 0 deletions interactive-clap-derive/docs/structs_to_cli_trait_docstring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
`interactive_clap::ToCli` derive

This module describes the derive logic of `#cli_name` struct used as `CliVariant` in
implementation of `interactive_clap::ToCli`, which happens during derive of [`crate::InteractiveClap`] for `#name` struct.

```rust,ignore
#[derive(Debug, Default, Clone, clap::Parser, interactive_clap::ToCliArgs)]
#[clap(author, version, about, long_about = None)]
pub struct #cli_name {
#( #cli_fields, )*
}

impl interactive_clap::ToCli for #name {
type CliVariant = #cli_name;
}
```

Where `interactive_clap::ToCli` is:

```rust,ignore
pub trait ToCli {
type CliVariant;
}
```
Additionally a [`clap::Parser`](https://docs.rs/clap/4.5.24/clap/trait.Parser.html) adapter
for `#name` and `From<#name> for #cli_name` conversion are defined:

```rust,ignore
impl #name {
pub fn try_parse() -> Result<#cli_name, clap::Error> {
<#cli_name as clap::Parser>::try_parse()
}

pub fn parse() -> #cli_name {
<#cli_name as clap::Parser>::parse()
}

pub fn try_parse_from<I, T>(itr: I) -> Result<#cli_name, clap::Error>
where
I: ::std::iter::IntoIterator<Item = T>,
T: ::std::convert::Into<::std::ffi::OsString> + ::std::clone::Clone,
{
<#cli_name as clap::Parser>::try_parse_from(itr)
}
}

impl From<#name> for #cli_name {
fn from(args: #name) -> Self {
Self {
#( #fields_conversion, )*
}
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
`interactive_clap::ToInteractiveClapContextScope` derive

This modules describes derive of `interactive_clap::ToInteractiveClapContextScope` trait for `#name` struct,
which happens during derive of [`crate::InteractiveClap`] for `#name` struct:

derive input `#name`

```rust,ignore
struct #name {
age: u64,
first_name: String,
}
```

gets transformed
=>

```rust,ignore
impl #name pub struct InteractiveClapContextScopeFor#name {
pub age: u64,
pub first_name: String,
}
impl interactive_clap::ToInteractiveClapContextScope for #name {
type InteractiveClapContextScope = InteractiveClapContextScopeFor#name;
}
```
22 changes: 22 additions & 0 deletions interactive-clap-derive/src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#[cfg(feature = "introspect")]
macro_rules! dbg_cond {
($($val:expr),* ) => {
dbg!($($val),*)
};
}

/// this macro under `introspect` feature can be used to debug how derive proc macros
/// ([`crate::InteractiveClap`], [`crate::ToCliArgs`]) work
///
/// ```bash
/// # interactive-clap-derive folder
/// cargo test test_doc_comments_propagate --features introspect -- --nocapture
/// # from repo root
/// cargo run --example struct_with_subargs --features interactive-clap-derive/introspect
/// ```
#[cfg(not(feature = "introspect"))]
macro_rules! dbg_cond {
($($val:expr),*) => {
// no-op
dj8yfo marked this conversation as resolved.
Show resolved Hide resolved
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub fn fn_choose_variant(
ast: &syn::DeriveInput,
variants: &syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
) -> proc_macro2::TokenStream {
dbg_cond!("entered `fn_choose_variant`");
let name = &ast.ident;
let interactive_clap_attrs_context =
super::interactive_clap_attrs_context::InteractiveClapAttrsContext::new(ast);
Expand All @@ -19,7 +20,9 @@ pub fn fn_choose_variant(
let mut ast_attrs: Vec<&str> = std::vec::Vec::new();

if !ast.attrs.is_empty() {
for attr in ast.attrs.clone() {
#[allow(clippy::unused_enumerate_index)]
for (_index, attr) in ast.attrs.clone().into_iter().enumerate() {
dbg_cond!(_index, &attr);
if attr.path.is_ident("interactive_clap") {
for attr_token in attr.tokens.clone() {
if let proc_macro2::TokenTree::Group(group) = attr_token {
Expand All @@ -29,16 +32,21 @@ pub fn fn_choose_variant(
}
}
};
dbg_cond!(attr.path.is_ident("strum_discriminants"));
if attr.path.is_ident("strum_discriminants") {
for attr_token in attr.tokens.clone() {
if let proc_macro2::TokenTree::Group(group) = attr_token {
if &group.stream().to_string() == "derive(EnumMessage, EnumIter)" {
let group_stream_no_whitespace =
group.stream().to_string().replace(" ", "");
dj8yfo marked this conversation as resolved.
Show resolved Hide resolved
dbg_cond!(&group_stream_no_whitespace);
if &group_stream_no_whitespace == "derive(EnumMessage,EnumIter)" {
ast_attrs.push("strum_discriminants");
};
}
}
};
}
dbg_cond!(&ast_attrs);
if ast_attrs.contains(&"strum_discriminants") {
let doc_attrs = ast
.attrs
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod choose_variant;
pub mod fields_with_skip_default_input_arg;
pub mod from_cli_for_enum;
pub mod interactive_clap_attrs_context;

This file was deleted.

Loading
Loading