diff --git a/src/attr.rs b/src/attr.rs
index 953c819c..765cff7c 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -1,9 +1,10 @@
 use syn::{
-    parse::{Parse, ParseStream},
-    punctuated::Punctuated,
-    LitStr, Token,
+    parse::{Parse, ParseBuffer, ParseStream},
+    Attribute, LitStr, Token,
 };
 
+use crate::Result;
+
 pub(crate) enum CommandAttrName {
     Prefix,
     Description,
@@ -49,20 +50,47 @@ impl Parse for CommandAttr {
     }
 }
 
-pub(crate) struct CommandAttrs(Punctuated<CommandAttr, Token![,]>);
+pub(crate) struct CommandAttrs(Vec<CommandAttr>);
 
-impl Parse for CommandAttrs {
-    fn parse(input: ParseStream) -> syn::Result<Self> {
-        input.parse_terminated(CommandAttr::parse).map(Self)
+impl CommandAttrs {
+    pub fn from_attributes(attributes: &[Attribute]) -> Result<Self> {
+        let mut attrs = Vec::new();
+
+        for attribute in attributes.iter().filter(is_command_attribute) {
+            let attrs_ = attribute.parse_args_with(|input: &ParseBuffer| {
+                input.parse_terminated::<_, Token![,]>(CommandAttr::parse)
+            })?;
+
+            attrs.extend(attrs_);
+        }
+
+        Ok(Self(attrs))
+    }
+}
+
+impl<'a> IntoIterator for &'a CommandAttrs {
+    type Item = &'a CommandAttr;
+
+    type IntoIter = std::slice::Iter<'a, CommandAttr>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.0.iter()
     }
 }
 
 impl IntoIterator for CommandAttrs {
     type Item = CommandAttr;
 
-    type IntoIter = syn::punctuated::IntoIter<CommandAttr>;
+    type IntoIter = std::vec::IntoIter<CommandAttr>;
 
     fn into_iter(self) -> Self::IntoIter {
         self.0.into_iter()
     }
 }
+
+fn is_command_attribute(a: &&Attribute) -> bool {
+    match a.path.get_ident() {
+        Some(ident) => ident == "command",
+        _ => false,
+    }
+}
diff --git a/src/command.rs b/src/command.rs
index b830c7c5..0c6dd064 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -1,5 +1,5 @@
 use crate::{
-    attr::{CommandAttr, CommandAttrName},
+    attr::{self, CommandAttr, CommandAttrName},
     command_enum::CommandEnum,
     fields_parse::ParserType,
     rename_rules::RenameRule,
@@ -14,7 +14,7 @@ pub(crate) struct Command {
 }
 
 impl Command {
-    pub fn try_from(attrs: &[CommandAttr], name: &str) -> Result<Self> {
+    pub fn try_from(attrs: attr::CommandAttrs, name: &str) -> Result<Self> {
         let attrs = parse_attrs(attrs)?;
         let CommandAttrs {
             prefix,
@@ -65,7 +65,7 @@ pub(crate) struct CommandAttrs {
     pub separator: Option<String>,
 }
 
-pub(crate) fn parse_attrs(attrs: &[CommandAttr]) -> Result<CommandAttrs> {
+pub(crate) fn parse_attrs(attrs: attr::CommandAttrs) -> Result<CommandAttrs> {
     let mut prefix = None;
     let mut description = None;
     let mut rename_rule = RenameRule::Identity;
@@ -74,13 +74,13 @@ pub(crate) fn parse_attrs(attrs: &[CommandAttr]) -> Result<CommandAttrs> {
 
     for CommandAttr { name, value } in attrs {
         match name {
-            CommandAttrName::Prefix => prefix = Some(value.clone()),
-            CommandAttrName::Description => description = Some(value.clone()),
-            CommandAttrName::Rename => rename_rule = RenameRule::parse(value)?,
+            CommandAttrName::Prefix => prefix = Some(value),
+            CommandAttrName::Description => description = Some(value),
+            CommandAttrName::Rename => rename_rule = RenameRule::parse(&value)?,
             CommandAttrName::ParseWith => {
-                parser = Some(ParserType::parse(value))
+                parser = Some(ParserType::parse(&value))
             }
-            CommandAttrName::Separator => separator = Some(value.clone()),
+            CommandAttrName::Separator => separator = Some(value),
         }
     }
 
diff --git a/src/command_enum.rs b/src/command_enum.rs
index c3248d6a..14aa0381 100644
--- a/src/command_enum.rs
+++ b/src/command_enum.rs
@@ -1,5 +1,5 @@
 use crate::{
-    attr::CommandAttr, command::parse_attrs, fields_parse::ParserType,
+    attr, command::parse_attrs, fields_parse::ParserType,
     rename_rules::RenameRule, Result,
 };
 
@@ -12,7 +12,7 @@ pub(crate) struct CommandEnum {
 }
 
 impl CommandEnum {
-    pub fn try_from(attrs: &[CommandAttr]) -> Result<Self> {
+    pub fn try_from(attrs: attr::CommandAttrs) -> Result<Self> {
         let attrs = parse_attrs(attrs)?;
 
         let prefix = attrs.prefix;
diff --git a/src/lib.rs b/src/lib.rs
index e7b8ae12..9a870d0d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,7 +11,7 @@ extern crate proc_macro;
 extern crate quote;
 extern crate syn;
 use crate::{
-    attr::{CommandAttr, CommandAttrs},
+    attr::CommandAttrs,
     command::Command,
     command_enum::CommandEnum,
     fields_parse::{impl_parse_args_named, impl_parse_args_unnamed},
@@ -31,28 +31,23 @@ fn bot_commands_impl(tokens: TokenStream) -> Result<TokenStream, Error> {
     let input = syn::parse_macro_input::parse::<DeriveInput>(tokens)?;
 
     let data_enum: &syn::DataEnum = get_enum_data(&input)?;
-    let enum_attrs: Vec<CommandAttr> = parse_attributes(&input.attrs)?;
-    let command_enum = CommandEnum::try_from(enum_attrs.as_slice())?;
+    let enum_attrs = CommandAttrs::from_attributes(&input.attrs)?;
+    let command_enum = CommandEnum::try_from(enum_attrs)?;
 
-    let variants: Vec<&syn::Variant> = data_enum.variants.iter().collect();
+    let variant_infos = data_enum
+        .variants
+        .iter()
+        .map(|variant| {
+            let attrs = CommandAttrs::from_attributes(&variant.attrs)?;
+            let command = Command::try_from(attrs, &variant.ident.to_string())?;
 
-    let mut variant_infos = vec![];
-    for variant in variants.iter() {
-        let mut attrs = Vec::new();
-        for attr in &variant.attrs {
-            let attrs_ = attr
-                .parse_args::<CommandAttrs>()
-                .map_err(|e| compile_error(e.to_compile_error()))?;
-            attrs.extend(attrs_);
-        }
-        let command =
-            Command::try_from(attrs.as_slice(), &variant.ident.to_string())?;
-
-        variant_infos.push(command);
-    }
+            Ok(command)
+        })
+        .collect::<Result<Vec<_>, Error>>()?;
 
     let mut vec_impl_create = vec![];
-    for (variant, info) in variants.iter().zip(variant_infos.iter()) {
+
+    for (variant, info) in data_enum.variants.iter().zip(variant_infos.iter()) {
         let var = &variant.ident;
         let variant_ = quote! { Self::#var };
         match &variant.fields {
@@ -182,18 +177,3 @@ fn get_enum_data(input: &DeriveInput) -> Result<&syn::DataEnum> {
         _ => Err(compile_error("TelegramBotCommand allowed only for enums")),
     }
 }
-
-fn parse_attributes(input: &[syn::Attribute]) -> Result<Vec<CommandAttr>> {
-    let mut enum_attrs = Vec::new();
-    for attr in input.iter() {
-        match attr.parse_args::<CommandAttrs>() {
-            Ok(attrs) => {
-                enum_attrs.extend(attrs);
-            }
-            Err(e) => {
-                return Err(compile_error(e.to_compile_error()));
-            }
-        }
-    }
-    Ok(enum_attrs)
-}