1#![doc = include_str!("../README.md")]
2
3use proc_macro::*;
4use Spacing::*;
5use tt_path::TtPath;
6
7fn stream<I>(iter: I) -> TokenStream
8where I: IntoIterator<Item = TokenTree>,
9{
10 TokenStream::from_iter(iter)
11}
12
13fn span_setter(span: Span) -> impl Fn(TokenTree) -> TokenTree {
14 move |mut tt| {
15 tt.set_span(span);
16 tt
17 }
18}
19
20fn err(msg: &str, span: Span) -> TokenStream {
21 let s = span_setter(span);
22 stream([
23 s(Punct::new(':', Joint).into()),
24 s(Punct::new(':', Joint).into()),
25 s(Ident::new("core", span).into()),
26 s(Punct::new(':', Joint).into()),
27 s(Punct::new(':', Joint).into()),
28 s(Ident::new("compile_error", span).into()),
29 s(Punct::new('!', Joint).into()),
30 s(Group::new(Delimiter::Brace, stream([
31 s(Literal::string(msg).into()),
32 ])).into()),
33 ])
34}
35
36struct Sorter {
37 key: TtPath,
38 prefix: TokenStream,
39 tokens: Vec<TokenTree>,
40 args: Group,
41}
42impl Sorter {
43 fn finish(self) -> TokenStream {
44 let mut args = self.args.stream().into_iter().collect::<Vec<_>>();
45 args.sort_by_key(|tt| {
46 self.key.apply(tt.clone())
47 .into_iter()
48 .filter_map(Result::ok)
49 .map(|it| it.to_string())
50 .collect::<Vec<_>>()
51 });
52 args.splice(..0, self.prefix);
53
54 let mut sorted_args = Group::new(self.args.delimiter(), TokenStream::from_iter(args));
55 sorted_args.set_span(self.args.span());
56
57 self.tokens.into_iter()
58 .chain([sorted_args.into()])
59 .collect()
60 }
61}
62
63#[doc = include_str!("../README.md")]
64#[proc_macro]
65pub fn sort_in(tokens: TokenStream) -> TokenStream {
66 let mut tokens = tokens.into_iter().collect::<Vec<_>>();
67 let Some(args) = tokens.pop() else {
68 return err("must input a `()` `{}` `[]`", Span::call_site());
69 };
70 let TokenTree::Group(args) = args else {
71 return err("last token must is group", args.span());
72 };
73
74 let mut prefix = TokenStream::new();
75 let mut key = TtPath::from_tokens(&mut None.into_iter().peekable()).unwrap();
76
77 if let Some(TokenTree::Group(first)) = tokens.first()
78 && first.delimiter() == Delimiter::Bracket
79 {
80 let iter = &mut first.stream().into_iter().peekable();
81 match TtPath::from_tokens(iter) {
82 Ok(tt_path) => key = tt_path,
83 Err(e) => return err(e.msg(), e.span()),
84 }
85 if let Some(peek) = iter.peek() {
86 return err("unexpected key token", peek.span());
87 }
88 tokens.remove(0);
89 }
90
91 if let Some(TokenTree::Group(first)) = tokens.first()
92 && first.delimiter() == Delimiter::Brace
93 {
94 prefix = first.stream();
95 tokens.remove(0);
96 }
97
98 Sorter { key, prefix, tokens, args }.finish()
99}