pythonic 0.2.4

pythonic is a Rust AST builder that generates Python
Documentation
use std::fmt::{Display, Formatter, Result};

#[derive(Debug, Clone)]
pub struct Argument {
    pub name: Option<String>,
    pub default: Option<String>,
    pub value: Option<String>,
    pub arg_type: Option<String>,
    pub help: Option<String>,
    argument_type: ArgumentType,
}

#[derive(Debug, Clone)]
enum ArgumentType {
    FunctionDefinition,
    FunctionCall {
        bare: bool,
    },
}

#[cfg(test)]
mod tests {
    mod definition {
        use Argument;

        #[test]
        fn it_prints_an_argument_with_no_default() {
            let arg = Argument::new("test", None, None, None);
            assert_eq!("test", format!("{}", arg));
        }

        #[test]
        fn it_prints_an_argument_with_a_default() {
            let arg = Argument::new("test", Some(r#""value""#), None, None);
            assert_eq!(r#"test="value""#, format!("{}", arg));
        }
    }

    mod bare_argument {
        use Argument;
        #[test]
        fn it_prints_an_argument() {
            let arg = Argument::bare("world");
            assert_eq!("\"world\"", format!("{}", arg));
        }
    }

    mod function_argument {
        use Argument;
        #[test]
        fn it_prints_an_argument() {
            let arg = Argument::input("name");
            assert_eq!("name", format!("{}", arg));
        }
    }

}

impl Argument {
    pub fn new<T: Display>(name: T,
                           default: Option<T>,
                           arg_type: Option<T>,
                           help: Option<T>)
                           -> Argument {
        Argument {
            name: Some(name.to_string()),
            default: default.map(|s| s.to_string()),
            value: None,
            arg_type: arg_type.map(|s| s.to_string()),
            help: help.map(|s| s.to_string()),
            argument_type: ArgumentType::FunctionDefinition,
        }
    }

    pub fn bare<T: Display>(value: T) -> Argument {
        Argument {
            name: None,
            default: None,
            value: Some(value.to_string()),
            arg_type: None,
            help: None,
            argument_type: ArgumentType::FunctionCall { bare: true },
        }
    }

    pub fn input<T: Display>(name: T) -> Argument {
        Argument {
            name: Some(name.to_string()),
            default: None,
            value: None,
            arg_type: None,
            help: None,
            argument_type: ArgumentType::FunctionCall { bare: false },
        }
    }

    pub fn has_help(&self) -> bool {
        self.help.is_some()
    }

    pub fn help_string(&self) -> String {
        if let Some(ref name) = self.name {
            let mut help = format!(":param {}:", name);

            if let Some(ref help_str) = self.help {
                help.push_str(&format!(" {}", help_str)[..]);
            }
            help
        } else {
            String::new()
        }
    }

    pub fn type_string(&self) -> String {
        if let Some(ref name) = self.name {
            let mut help = format!(":type {}:", name);
            if let Some(ref t) = self.arg_type {
                help.push_str(&format!(" {}", t)[..]);
            }
            help
        } else {
            String::new()
        }
    }
}

impl Display for Argument {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut output = String::new();
        match self.argument_type {
            ArgumentType::FunctionDefinition => {
                if let Some(ref name) = self.name {
                    output.push_str(&name[..]);
                } else {
                    panic!("You must provide a name for a function definition's argument")
                }
                if let Some(ref default) = self.default {
                    output.push_str(&format!("={}", default)[..]);
                }
            }
            ArgumentType::FunctionCall { bare: true } => {
                if let Some(ref value) = self.value {
                    output.push_str(&format!("\"{}\"", value)[..]);
                } else {
                    panic!("You must provide a value for a bare argument")
                }
            }
            ArgumentType::FunctionCall { bare: false } => {
                if let Some(ref name) = self.name {
                    output.push_str(&format!("{}", name)[..]);
                } else {
                    panic!("You must provide a name for a function call")
                }
            }
        }
        write!(f, "{}", output)
    }
}

#[derive(Debug, Clone)]
pub struct KeywordArgument {
    pub keyword: String,
    pub argument: String,
}

impl KeywordArgument {
    pub fn new<T: Display>(name: T, arg: T) -> KeywordArgument {
        KeywordArgument {
            keyword: name.to_string(),
            argument: arg.to_string(),
        }
    }
}

impl Display for KeywordArgument {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}={}", self.keyword, self.argument)
    }
}