-
Notifications
You must be signed in to change notification settings - Fork 8
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
Derive a form (multiple prompts) from struct #11
Comments
@simonsan Thank you for your proposal!
Currently, we do not offer such a feature (this is simply because I am not yet well-versed in Derive/macro). However, setting aside the specifics of the interface, I understand what you are looking to achieve and I am very interested in it. |
Nice! In one issue, there is an example/demo of how such a thing could work: https://github.com/IniterWorker/inquire_derive Maybe it helps to get started. Also, there is the The Little Book of Rust Macros and there is the proc-macro workshop by dtolnay. I'm saying this, because I'm trying to support and hope that such a thing will exist at one point in time, as I think it would be really valuable to the ecosystem. (: |
@simonsan I've started by creating a prototype. I believe it needs to be refined further, but what do you think? use promkit::{crossterm::style::Color, style::StyleBuilder, Result};
use promkit_derive::Promkit;
#[derive(Default, Debug, Promkit)]
struct MyStruct {
#[ask(
prefix = "What is your name?",
prefix_style = StyleBuilder::new().fgc(Color::DarkCyan).build(),
)]
name: String,
#[ask(prefix = "How old are you?", ignore_invalid_attr = "nothing")]
age: usize,
}
fn main() -> Result {
let ret = MyStruct::default().ask_name()?.ask_age()?;
dbg!(ret);
Ok(())
} |
Looks really nice! 👍🏽 I need to try it out, to see if the API is ergonomic for me. But the way you instantiate and do it, is exactly how I would imagine it. In the end, it's like a builder pattern, that is being exposed directly to the user. For example, if you would like to ask for each field in the struct it would be pleasant to have a short calling method like Which would internally call
Great work! 🌷 |
@simonsan Thank you for your comment! 👍 Please feel free to continue posting your feedback after you have had a chance to try it out. As a favor, could I ask for the opportunity to have you take another review the macro after I've refined it based on your feedback? |
For sure! :) 👍🏽 |
@simonsan I refined it in PR #17. Here are the changes:
The concerns are as follows, and I would appreciate your opinions:
Example: use promkit::{crossterm::style::Color, style::StyleBuilder, Result};
use promkit_derive::Promkit;
#[derive(Default, Debug, Promkit)]
struct Profile {
#[readline(
prefix = "What is your name?",
prefix_style = StyleBuilder::new().fgc(Color::DarkCyan).build(),
)]
name: String,
#[readline(default)]
hobby: Option<String>,
#[readline(prefix = "How old are you?", ignore_invalid_attr = "nothing")]
age: usize,
}
fn main() -> Result {
let mut ret = Profile::default();
ret.readline_name()?;
ret.readline_hobby()?;
ret.readline_age()?;
dbg!(ret);
Ok(())
} Thanks 👍 |
I'm on the way to going out, so only tiny feedback:
/// Tags for the activity
#[cfg_attr(
feature = "clap",
clap(
short,
long,
group = "adjust",
name = "Tags",
value_name = "Tags",
visible_alias = "tag",
value_delimiter = ','
)
)]
tags: Option<Vec<String>>,
|
Some naming ideas: For the
For the
|
@simonsan Thanks for your comments! 👍 Indeed, the terminology needs to be clearer about what can be done. It felt like it could also be offered as something separate from presets. Accepting collections with delimiters is a good idea. On the other hand, incorporating various parser logics might make the macro complex (it already seemed quite complex when allowing for |
Some idea: use promkit::{crossterm::style::Color, style::StyleBuilder, Result};
use promkit_derive::Form;
#[derive(Default, Debug, Form)]
struct Profile {
#[input(
prompt = "What is your name?",
prompt_style = StyleBuilder::new().fgc(Color::DarkCyan).build(),
)]
name: String,
#[input(default)]
hobby: Option<String>,
#[input(prompt = "How old are you?", ignore_invalid_attr = "nothing")]
age: usize,
}
fn main() -> Result {
let mut ret = Profile::default();
ret.prompt_name()?;
ret.prompt_hobby()?;
ret.prompt_age()?;
dbg!(ret);
Ok(())
}
use promkit_derive::FormBuilder;
#[derive(Default, Debug, FormBuilder)] |
A form could be even layouted like this: Please fill out the form:
------------------------
What is your name?: John Doe
What is your hobby? (Leave empty if none):
How old are you?: 25
Use Up/Down to navigate through the inputs
Press Enter if you are ready to continue I don't know if that is easily possible, though 😅 It's not a dealbreaker, would just double down on the |
I agree completely. We don't want to make it too complex. I think |
I found this one from the Go ecosystem, which might be also interesting from a design perspective: |
From this comment. @simonsan I was on a bit of a journey to working on some projects like jnv and sig (and also doing the actual travel). I'm gradually returning to this development. Apologies for the delay in my response.
I’ve prepared the form-like UI (ref) mentioned in your previous comment and I'm currently updating the derive to use this form mechanism instead of |
I would like to easily annotate a configuration struct, to ask the user for input for various fields and give a hint on validation:
I would be interested if something like this is already existing, e.g. based on inquire, promkit, or if there is any interest to add this?
There are some ideas already in
inquire
, but it feels a bit out of scope.CC: mikaelmello/inquire#212
CC: mikaelmello/inquire#65
EDIT: It would basically be the
clap
way of doing interactive prompts. Annotate something and give it to the user to let it be filled out. I think it comes with its own advantages and disadvantages, and excels a lot in a workflow where you suddenly want the user to fill out some data you already have bundled in a struct.I think it could be a game changing feature, though. Because it would make dealing with interactive prompts much easier for a lot of users. Also, it would be excellent to have for people that don't want the full-fledged control of a
ratatui
TUI, but still a bit more ergonomic when it comes to interactivity and developer experience creating such.The text was updated successfully, but these errors were encountered: