1#![doc = include_str!("../README.md")]
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::LitStr;
6use syn::parse_macro_input;
7
8include!(concat!(env!("OUT_DIR"), "/glyphs.rs"));
9
10#[proc_macro]
17pub fn nf(input: TokenStream) -> TokenStream {
18 let glyph_name = parse_macro_input!(input as LitStr).value();
19
20 if let Some(&glyph) = GLYPHS.get(glyph_name.as_str()) {
21 quote!(#glyph)
22 } else {
23 let mut message = format!("Unknown Nerd Font glyph `{glyph_name}`.");
24
25 let mut candidates =
26 GLYPHS
27 .keys()
28 .map(|&key| (strsim::jaro_winkler(&glyph_name, key), key))
29 .filter(|&(score, _)| score > 0.75)
30 .collect::<Vec<_>>();
31 candidates.sort_by(|a, b| f64::total_cmp(&b.0, &a.0));
32
33 let suggestions =
34 candidates
35 .into_iter()
36 .take(3)
37 .map(|(_, candidate)| format!("`{candidate}`"))
38 .collect::<Vec<_>>();
39
40 if !suggestions.is_empty() {
41 message.push_str(" Did you mean one of: ");
42 message.push_str(&suggestions.join(", "));
43 message.push('?');
44 }
45
46 quote!(compile_error!(#message))
47 }.into()
48}