aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-08-02 12:11:47 +0800
committer魏曹先生 <1992414357@qq.com>2026-08-02 12:11:47 +0800
commit43fadfa22b1f28382338c892d91a6c388b5e540c (patch)
treefb986e1d4fa65801a8ced895e43c135921328cad
parent0f9ca0745e3e80c751404f45cb2b97d4d14c97d3 (diff)
feat(core): add batch methods to Suggest and update macro
Add `add_suggest()` and `add_suggest_with_description()` methods to `Suggest` for ergonomic batch population of suggestion sets from collections of strings. Update the `suggest!` macro to use these new methods and accept expressions beyond string literals for suggestion items.
-rw-r--r--CHANGELOG.md7
-rw-r--r--mingling_core/src/comp/suggest.rs36
-rw-r--r--mingling_macros/src/func/suggest.rs43
3 files changed, 74 insertions, 12 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d46f4d..4780d0f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -72,6 +72,13 @@ None
_No behavioral change for downstream code — all public items are re-exported with the same names. The `__this_program_impl` module is `#[doc(hidden)]` and not part of the public API._
+3. **[`core:comp`]** Added `add_suggest()` and `add_suggest_with_description()` methods to `Suggest` for batch-adding suggestion items:
+
+ - **`add_suggest(&mut self, items: impl Into<Vec<String>>)`** — Wraps each item in `SuggestItem::Simple` and inserts it into the underlying `BTreeSet`.
+ - **`add_suggest_with_description(&mut self, items: impl Into<Vec<String>>, desc: impl Into<String>)`** — Wraps each item in `SuggestItem::WithDescription` using the provided description and inserts it into the set.
+
+ These methods enable ergonomic batch population of suggestion sets from collections of strings, complementing the existing `insert()` method.
+
#### Features:
1. **[`picker:value:paths`]** Added new path wrapper types to `arg_picker::value` for filesystem-aware argument parsing:
diff --git a/mingling_core/src/comp/suggest.rs b/mingling_core/src/comp/suggest.rs
index 88fa5fc..dda5026 100644
--- a/mingling_core/src/comp/suggest.rs
+++ b/mingling_core/src/comp/suggest.rs
@@ -56,6 +56,42 @@ impl Suggest {
(suggest, _) => suggest,
}
}
+
+ /// Adds multiple simple suggestions (without descriptions) to the `Suggest` set.
+ ///
+ /// Each item produced by the iterator is wrapped in a [`SuggestItem::Simple`]
+ /// variant and inserted into the underlying `BTreeSet`.
+ ///
+ /// # Arguments
+ ///
+ /// * `items` — A collection of suggestion strings to add.
+ pub fn add_suggest(&mut self, items: impl Into<Vec<String>>) {
+ for item in items.into() {
+ self.insert(SuggestItem::Simple(item));
+ }
+ }
+
+ /// Adds multiple suggestions with a shared description to the `Suggest` set.
+ ///
+ /// Each item produced by the iterator is wrapped in a
+ /// [`SuggestItem::WithDescription`] variant using the provided description,
+ /// and inserted into the underlying `BTreeSet`.
+ ///
+ /// # Arguments
+ ///
+ /// * `items` — A collection of suggestion strings to add.
+ /// * `desc` — The description to attach to each suggestion. Must implement
+ /// `Into<String>`.
+ pub fn add_suggest_with_description(
+ &mut self,
+ items: impl Into<Vec<String>>,
+ desc: impl Into<String>,
+ ) {
+ let desc_str = desc.into();
+ for item in items.into() {
+ self.insert(SuggestItem::WithDescription(item, desc_str.clone()));
+ }
+ }
}
impl<T> From<T> for Suggest
diff --git a/mingling_macros/src/func/suggest.rs b/mingling_macros/src/func/suggest.rs
index 85f1afe..6613a98 100644
--- a/mingling_macros/src/func/suggest.rs
+++ b/mingling_macros/src/func/suggest.rs
@@ -2,15 +2,15 @@ use proc_macro::TokenStream;
use quote::quote;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
-use syn::{Expr, LitStr, Token, parse_macro_input};
+use syn::{Expr, Token, parse_macro_input};
struct SuggestInput {
items: Punctuated<SuggestItem, Token![,]>,
}
enum SuggestItem {
- WithDesc(Box<(LitStr, Expr)>), // "-i" = "Insert something"
- Simple(LitStr), // "-I"
+ WithDesc(Box<(Expr, Expr)>), // "-i" = "Insert something"
+ Simple(Expr), // "-I"
}
impl Parse for SuggestInput {
@@ -22,7 +22,7 @@ impl Parse for SuggestInput {
impl Parse for SuggestItem {
fn parse(input: ParseStream) -> syn::Result<Self> {
- let key: LitStr = input.parse()?;
+ let key: Expr = input.parse()?;
if input.peek(Token![:]) {
let _colon: Token![:] = input.parse()?;
@@ -34,36 +34,55 @@ impl Parse for SuggestItem {
}
}
+/// 判断表达式是否是一个纯字符串字面量(仅由一对引号包裹)
+fn is_pure_lit_str(expr: &Expr) -> bool {
+ matches!(expr, Expr::Lit(lit) if matches!(lit.lit, syn::Lit::Str(_)))
+}
+
#[cfg(feature = "comp")]
pub(crate) fn suggest(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as SuggestInput);
let mut items = Vec::new();
+ let mut simple_items = Vec::new();
for item in input.items {
match item {
SuggestItem::WithDesc(boxed) => {
let (key, value) = *boxed;
- items.push(quote! {
- ::mingling::SuggestItem::new_with_desc(#key.to_string(), #value.to_string())
- });
+ if is_pure_lit_str(&key) {
+ items.push(quote! {
+ vec![#key .to_string()], #value
+ });
+ } else {
+ items.push(quote! {
+ #key, #value
+ });
+ }
}
SuggestItem::Simple(key) => {
- items.push(quote! {
- ::mingling::SuggestItem::new(#key.to_string())
- });
+ if is_pure_lit_str(&key) {
+ simple_items.push(quote! {
+ vec![#key .to_string()]
+ });
+ } else {
+ simple_items.push(quote! {
+ #key
+ });
+ }
}
}
}
- let expanded = if items.is_empty() {
+ let expanded = if items.is_empty() && simple_items.is_empty() {
quote! {
::mingling::Suggest::new()
}
} else {
quote! {{
let mut suggest = ::mingling::Suggest::new();
- #(suggest.insert(#items);)*
+ #(suggest.add_suggest_with_description(#items);)*
+ #(suggest.add_suggest(#simple_items);)*
suggest
}}
};