From 8b808de6ff9aed5c631f088bf1293874b5299cff Mon Sep 17 00:00:00 2001 From: Aaron Lobb Date: Mon, 14 Sep 2015 00:29:15 -0700 Subject: [PATCH] Fixed https://github.com/nrc/rustfmt/issues/291; added output to --help runtime option with possible config values --- src/bin/rustfmt.rs | 11 ++++ src/config.rs | 122 +++++++++++++++++++++++++++++++++------------ src/utils.rs | 11 ++++ 3 files changed, 113 insertions(+), 31 deletions(-) diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 9913c68cdfa..f2eb4f46ac1 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -18,6 +18,7 @@ extern crate toml; use rustfmt::{WriteMode, run}; use rustfmt::config::Config; +use rustfmt::config::ConfigHelpVariantTypes; use std::env; use std::fs::{File, PathExt}; @@ -85,6 +86,16 @@ fn print_usage>(reason: S) { println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display|diff]] \ ", reason.into()); + + for option in Config::get_docs() { + let variants = option.variant_names(); + let variant_names: String = match *variants { + ConfigHelpVariantTypes::UsizeConfig => "".into(), + ConfigHelpVariantTypes::BoolConfig => "".into(), + ConfigHelpVariantTypes::EnumConfig(ref variants) => variants.join(", "), + }; + println!("{}, {}, Possible values: {}", option.option_name(), option.doc_string(), variant_names); + } } fn determine_params(args: I) -> Option<(Vec, WriteMode)> diff --git a/src/config.rs b/src/config.rs index d45f184051f..4026ea856cb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -66,7 +66,7 @@ impl MultilineStyle { } macro_rules! create_config { - ($($i:ident: $ty:ty),+ $(,)*) => ( + ($($i:ident: $ty:ty, $dstring: tt),+ $(,)*) => ( #[derive(RustcDecodable, Clone)] pub struct Config { $(pub $i: $ty),+ @@ -82,6 +82,50 @@ macro_rules! create_config { $(pub $i: Option<$ty>),+ } + // This trait and the following impl blocks are there only so that we + // can use UCFS inside the get_docs() function on builtin types for configs. + trait IsConfigType { + fn get_variant_names() -> Vec<&'static str>; + } + + impl IsConfigType for bool { + fn get_variant_names() -> Vec<&'static str> { + unreachable!() + } + } + + impl IsConfigType for usize { + fn get_variant_names() -> Vec<&'static str> { + unreachable!() + } + } + + pub struct ConfigHelpItem { + option_name: &'static str, + doc_string : &'static str, + variant_names: ConfigHelpVariantTypes, + } + + pub enum ConfigHelpVariantTypes { + UsizeConfig, + BoolConfig, + EnumConfig(Vec<&'static str>), + } + + impl ConfigHelpItem { + pub fn option_name(&self) -> &'static str { + self.option_name + } + + pub fn doc_string(&self) -> &'static str { + self.doc_string + } + + pub fn variant_names(&self) -> &ConfigHelpVariantTypes { + &self.variant_names + } + } + impl Config { fn fill_from_parsed_config(mut self, parsed: &ParsedConfig) -> Config { @@ -117,41 +161,57 @@ macro_rules! create_config { _ => panic!("Bad config key!") } } + + pub fn get_docs() -> Vec { + let mut options: Vec = Vec::new(); + $( + let config_variant_type = match stringify!($ty) { + "bool" => ConfigHelpVariantTypes::BoolConfig, + "usize" => ConfigHelpVariantTypes::UsizeConfig, + _ => ConfigHelpVariantTypes::EnumConfig(<$ty>::get_variant_names()), + }; + options.push(ConfigHelpItem { + option_name: stringify!($i), + doc_string: stringify!($dstring), + variant_names: config_variant_type, + }); + )+ + options + } } ) } create_config! { - max_width: usize, - ideal_width: usize, - leeway: usize, - tab_spaces: usize, - newline_style: NewlineStyle, - fn_brace_style: BraceStyle, - fn_return_indent: ReturnIndent, - fn_args_paren_newline: bool, - fn_args_density: Density, - fn_args_layout: StructLitStyle, - fn_arg_indent: BlockIndentStyle, - where_density: Density, // Should we at least try to put the where clause on - // the same line as the rest of the function decl? - where_indent: BlockIndentStyle, // Visual will be treated like Tabbed - where_layout: ListTactic, - where_pred_indent: BlockIndentStyle, - generics_indent: BlockIndentStyle, - struct_trailing_comma: SeparatorTactic, - struct_lit_trailing_comma: SeparatorTactic, - struct_lit_style: StructLitStyle, - struct_lit_multiline_style: MultilineStyle, - enum_trailing_comma: bool, - report_todo: ReportTactic, - report_fixme: ReportTactic, - reorder_imports: bool, // Alphabetically, case sensitive. - single_line_if_else: bool, - format_strings: bool, - chains_overflow_last: bool, - take_source_hints: bool, // Retain some formatting characteristics from - // the source code. + max_width: usize, "Maximum width of each line", + ideal_width: usize, "Ideal width of each line", + leeway: usize, "Leeway of line width", + tab_spaces: usize, "Number of spaces per tab", + newline_style: NewlineStyle, "Unix or Windows line endings", + fn_brace_style: BraceStyle, "Brace style for functions", + fn_return_indent: ReturnIndent, "Location of return type in function declaration", + fn_args_paren_newline: bool, "If function argument parenthases goes on a newline", + fn_args_density: Density, "Argument density in functions", + fn_args_layout: StructLitStyle, "Layout of function arguments", + fn_arg_indent: BlockIndentStyle, "Indent on function arguments", + where_density: Density, "Density of a where clause", // Should we at least try to put the where clause on the same line as + // the rest of the function decl? + where_indent: BlockIndentStyle, "Indentation of a where clause", // Visual will be treated like Tabbed + where_layout: ListTactic, "Element layout inside a where clause", + where_pred_indent: BlockIndentStyle, "Indentation style of a where predicate", + generics_indent: BlockIndentStyle, "Indentation of generics", + struct_trailing_comma: SeparatorTactic, "If there is a trailing comma on structs", + struct_lit_trailing_comma: SeparatorTactic, "If there is a trailing comma on literal structs", + struct_lit_style: StructLitStyle, "Style of struct definition", + struct_lit_multiline_style: MultilineStyle, "Multilline style on literal structs", + enum_trailing_comma: bool, "Put a trailing comma on enum declarations", + report_todo: ReportTactic, "Report all occurences of TODO in source file comments", + report_fixme: ReportTactic, "Report all occurences of FIXME in source file comments", + reorder_imports: bool, "Reorder import statements alphabetically", // Alphabetically, case sensitive. + single_line_if_else: bool, "Put else on same line as closing brace for if statements", + format_strings: bool, "Format string literals, or leave as is", + chains_overflow_last: bool, "chains overflow last", + take_source_hints: bool, "Retain some formatting characteristics from the source code", } impl Default for Config { diff --git a/src/utils.rs b/src/utils.rs index 973f0fa56ab..0ba0c2c4a48 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -161,6 +161,17 @@ macro_rules! impl_enum_decodable { } } } + + impl $e { + pub fn get_variant_names() -> Vec<&'static str> { + let mut variants = Vec::new(); + $( + variants.push(stringify!($x)); + )* + + variants + } + } }; }