notation_dsl/fretted/
pick.rs1use fehler::throws;
2use notation_proto::prelude::{CoreEntry, FrettedEntry4, FrettedEntry6, Pick};
3use notation_proto::proto_entry::ProtoEntry;
4use proc_macro2::TokenStream;
5use quote::{quote, ToTokens};
6use syn::parse::{Error, ParseStream};
7use syn::{LitInt, Token};
8
9use crate::context::Context;
10use crate::core::duration::DurationTweakDsl;
11
12use super::pick_note::PickNoteDsl;
13
14pub struct PickDsl {
15 pub notes: Vec<PickNoteDsl>,
16 pub duration_tweak: Option<DurationTweakDsl>,
17}
18
19impl PickDsl {
20 #[throws(Error)]
21 pub fn parse_without_paren(input: ParseStream, multied: bool, with_paren: bool) -> Self {
22 let mut notes = vec![];
23 if input.peek(Token![_]) {
24 input.parse::<Token![_]>()?;
25 } else {
26 while input.peek(LitInt) {
27 notes.push(input.parse()?);
28 if multied && !with_paren {
29 break;
30 }
31 }
32 }
33 let duration_tweak = DurationTweakDsl::try_parse(input);
34 PickDsl {
35 notes,
36 duration_tweak,
37 }
38 }
39}
40
41impl ToTokens for PickDsl {
42 fn to_tokens(&self, tokens: &mut TokenStream) {
43 let PickDsl {
44 notes,
45 duration_tweak,
46 } = self;
47 let duration_quote = Context::duration_quote(duration_tweak);
48 if notes.len() == 0 {
49 tokens.extend(quote! {
50 ProtoEntry::from(CoreEntry::from(#duration_quote))
51 });
52 } else {
53 let _string_num = Context::fretted().string_num;
54 let notes_quote: Vec<_> = notes.iter().map(|x| quote! { #x }).collect();
55 let fretted_entry_quote = Context::fretted().fretted_entry_quote();
56 tokens.extend(quote! {
57 ProtoEntry::from(#fretted_entry_quote::from(
58 (Pick::from(vec![
59 #(#notes_quote),*
60 ]), #duration_quote)
61 ))
62 });
63 }
64 }
65}
66
67impl PickDsl {
68 pub fn to_proto(&self) -> ProtoEntry {
69 let PickDsl {
70 notes,
71 duration_tweak,
72 } = self;
73 let duration = Context::tweaked_duration(duration_tweak);
74 if notes.len() == 0 {
75 ProtoEntry::from(CoreEntry::from(duration))
76 } else {
77 let _string_num = Context::fretted().string_num;
78 let notes: Vec<_> = notes.iter().map(|x| x.to_proto()).collect();
79 match Context::fretted().string_num {
80 4 => ProtoEntry::from(FrettedEntry4::from((Pick::from(notes), duration))),
81 _ => ProtoEntry::from(FrettedEntry6::from((Pick::from(notes), duration))),
82 }
83 }
84 }
85}