about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/rustfmt.rs12
-rw-r--r--src/changes.rs3
-rw-r--r--src/default.toml9
-rw-r--r--src/expr.rs4
-rw-r--r--src/functions.rs21
-rw-r--r--src/lib.rs73
-rw-r--r--src/visitor.rs16
7 files changed, 96 insertions, 42 deletions
diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs
index 32c38ea15e4..5a12dbd639b 100644
--- a/src/bin/rustfmt.rs
+++ b/src/bin/rustfmt.rs
@@ -15,10 +15,18 @@ extern crate rustfmt;
 
 use rustfmt::{WriteMode, run};
 
+use std::fs::File;
+use std::io::Read;
+
 fn main() {
     let args: Vec<_> = std::env::args().collect();
-    //run(args, WriteMode::Display);
-    run(args, WriteMode::Overwrite);
+    let mut def_config_file = File::open("default.toml").unwrap();
+    let mut def_config = String::new();
+    def_config_file.read_to_string(&mut def_config).unwrap();
+
+    //run(args, WriteMode::Display, &def_config);
+    run(args, WriteMode::Overwrite, &def_config);
+
     std::env::set_exit_status(0);
 
     // TODO unit tests
diff --git a/src/changes.rs b/src/changes.rs
index f0aebe7c94f..5ed1c82b22f 100644
--- a/src/changes.rs
+++ b/src/changes.rs
@@ -20,7 +20,6 @@ use std::fmt;
 use std::fs::File;
 use std::io::{Write, stdout};
 use WriteMode;
-use NEWLINE_STYLE;
 use NewlineStyle;
 
 // This is basically a wrapper around a bunch of Ropes which makes it convenient
@@ -157,7 +156,7 @@ impl<'a> ChangeSet<'a> {
             -> Result<(), ::std::io::Error>
             where T: Write,
         {
-            match NEWLINE_STYLE {
+            match config!(newline_style) {
                 NewlineStyle::Unix => write!(writer, "{}", text),
                 NewlineStyle::Windows => {
                     for (c, _) in text.chars() {
diff --git a/src/default.toml b/src/default.toml
index e049dfa59ba..218f2a04fb2 100644
--- a/src/default.toml
+++ b/src/default.toml
@@ -1,2 +1,7 @@
-max-width = 100
-ideal-width = 80
+max_width = 100
+ideal_width = 80
+leeway = 5
+tab_spaces = 4
+newline_style = "Unix"
+fn_brace_style = "SameLineWhere"
+fn_return_indent = "WithArgs"
diff --git a/src/expr.rs b/src/expr.rs
index 1da66c4e328..c1cbf175645 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -15,7 +15,7 @@ use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic};
 use syntax::{ast, ptr};
 use syntax::codemap::{Span, Pos};
 
-use {MAX_WIDTH, MIN_STRING};
+use MIN_STRING;
 
 impl<'a> FmtVisitor<'a> {
     // TODO NEEDS TESTS
@@ -26,7 +26,7 @@ impl<'a> FmtVisitor<'a> {
         // strings, or if the string is too long for the line.
         let l_loc = self.codemap.lookup_char_pos(span.lo);
         let r_loc = self.codemap.lookup_char_pos(span.hi);
-        if l_loc.line == r_loc.line && r_loc.col.to_usize() <= MAX_WIDTH {
+        if l_loc.line == r_loc.line && r_loc.col.to_usize() <= config!(max_width) {
             return self.snippet(span);
         }
 
diff --git a/src/functions.rs b/src/functions.rs
index 2133b7c4418..2ca5423f0c8 100644
--- a/src/functions.rs
+++ b/src/functions.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {ReturnIndent, MAX_WIDTH, BraceStyle,
-     IDEAL_WIDTH, LEEWAY, FN_BRACE_STYLE, FN_RETURN_INDENT};
+use {ReturnIndent, BraceStyle};
 use utils::make_indent;
 use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic};
 use visitor::FmtVisitor;
@@ -149,8 +148,8 @@ impl<'a> FmtVisitor<'a> {
             // If we've already gone multi-line, or the return type would push
             // over the max width, then put the return type on a new line.
             if result.contains("\n") ||
-               result.len() + indent + ret_str.len() > MAX_WIDTH {
-                let indent = match FN_RETURN_INDENT {
+               result.len() + indent + ret_str.len() > config!(max_width) {
+                let indent = match config!(fn_return_indent) {
                     ReturnIndent::WithWhereClause => indent + 4,
                     // TODO we might want to check that using the arg indent doesn't
                     // blow our budget, and if it does, then fallback to the where
@@ -344,15 +343,15 @@ impl<'a> FmtVisitor<'a> {
             if !newline_brace {
                 used_space += 2;
             }
-            let one_line_budget = if used_space > MAX_WIDTH {
+            let one_line_budget = if used_space > config!(max_width) {
                 0
             } else {
-                MAX_WIDTH - used_space
+                config!(max_width) - used_space
             };
 
             // 2 = `()`
             let used_space = indent + result.len() + 2;
-            let max_space = IDEAL_WIDTH + LEEWAY;
+            let max_space = config!(ideal_width) + config!(leeway);
             debug!("compute_budgets_for_args: used_space: {}, max_space: {}",
                    used_space, max_space);
             if used_space < max_space {
@@ -368,7 +367,7 @@ impl<'a> FmtVisitor<'a> {
             result.push_str(&make_indent(indent + 4));
             // 6 = new indent + `()`
             let used_space = indent + 6;
-            let max_space = IDEAL_WIDTH + LEEWAY;
+            let max_space = config!(ideal_width) + config!(leeway);
             if used_space > max_space {
                 // Whoops! bankrupt.
                 // TODO take evasive action, perhaps kill the indent or something.
@@ -382,7 +381,7 @@ impl<'a> FmtVisitor<'a> {
     }
 
     fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool {
-        match FN_BRACE_STYLE {
+        match config!(fn_brace_style) {
             BraceStyle::AlwaysNextLine => true,
             BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true,
             _ => false,
@@ -399,7 +398,7 @@ impl<'a> FmtVisitor<'a> {
             return result;
         }
 
-        let budget = MAX_WIDTH - indent - 2;
+        let budget = config!(max_width) - indent - 2;
         // TODO might need to insert a newline if the generics are really long
         result.push('<');
 
@@ -475,7 +474,7 @@ impl<'a> FmtVisitor<'a> {
                                                         .zip(comments.into_iter())
                                                         .collect();
 
-        let budget = IDEAL_WIDTH + LEEWAY - indent - 10;
+        let budget = config!(ideal_width) + config!(leeway) - indent - 10;
         let fmt = ListFormatting {
             tactic: ListTactic::Vertical,
             separator: ",",
diff --git a/src/lib.rs b/src/lib.rs
index 08ee465dddf..1c0fe0105ef 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -24,13 +24,17 @@ extern crate getopts;
 extern crate rustc;
 extern crate rustc_driver;
 extern crate syntax;
+extern crate rustc_serialize;
 
 extern crate strings;
 
 use rustc::session::Session;
-use rustc::session::config::{self, Input};
+use rustc::session::config as rustc_config;
+use rustc::session::config::Input;
 use rustc_driver::{driver, CompilerCalls, Compilation};
 
+use rustc_serialize::{Decodable, Decoder};
+
 use syntax::ast;
 use syntax::codemap::CodeMap;
 use syntax::diagnostics;
@@ -42,6 +46,8 @@ use std::collections::HashMap;
 use changes::ChangeSet;
 use visitor::FmtVisitor;
 
+#[macro_use]
+mod config;
 mod changes;
 mod visitor;
 mod functions;
@@ -52,17 +58,12 @@ mod types;
 mod expr;
 mod imports;
 
-const IDEAL_WIDTH: usize = 80;
-const LEEWAY: usize = 5;
-const MAX_WIDTH: usize = 100;
 const MIN_STRING: usize = 10;
-const TAB_SPACES: usize = 4;
-const NEWLINE_STYLE: NewlineStyle = NewlineStyle::Unix;
-const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere;
-const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs;
 // When we get scoped annotations, we should have rustfmt::skip.
 const SKIP_ANNOTATION: &'static str = "rustfmt_skip";
 
+static mut CONFIG: Option<config::Config> = None;
+
 #[derive(Copy, Clone)]
 pub enum WriteMode {
     Overwrite,
@@ -75,13 +76,24 @@ pub enum WriteMode {
 }
 
 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
-enum NewlineStyle {
+pub enum NewlineStyle {
     Windows, // \r\n
     Unix, // \n
 }
 
+impl Decodable for NewlineStyle {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+        let s = try!(d.read_str());
+        match &*s {
+            "Windows" => Ok(NewlineStyle::Windows),
+            "Unix" => Ok(NewlineStyle::Unix),
+            _ => Err(d.error("Bad variant")),
+        }
+    }
+}
+
 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
-enum BraceStyle {
+pub enum BraceStyle {
     AlwaysNextLine,
     PreferSameLine,
     // Prefer same line except where there is a where clause, in which case force
@@ -89,15 +101,39 @@ enum BraceStyle {
     SameLineWhere,
 }
 
+impl Decodable for BraceStyle {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+        let s = try!(d.read_str());
+        match &*s {
+            "AlwaysNextLine" => Ok(BraceStyle::AlwaysNextLine),
+            "PreferSameLine" => Ok(BraceStyle::PreferSameLine),
+            "SameLineWhere" => Ok(BraceStyle::SameLineWhere),
+            _ => Err(d.error("Bad variant")),
+        }
+    }
+}
+
 // How to indent a function's return type.
 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
-enum ReturnIndent {
+pub enum ReturnIndent {
     // Aligned with the arguments
     WithArgs,
     // Aligned with the where clause
     WithWhereClause,
 }
 
+// TODO could use a macro for all these Decodable impls.
+impl Decodable for ReturnIndent {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+        let s = try!(d.read_str());
+        match &*s {
+            "WithArgs" => Ok(ReturnIndent::WithArgs),
+            "WithWhereClause" => Ok(ReturnIndent::WithWhereClause),
+            _ => Err(d.error("Bad variant")),
+        }
+    }
+}
+
 // Formatting which depends on the AST.
 fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> {
     let mut visitor = FmtVisitor::from_codemap(codemap);
@@ -133,10 +169,10 @@ fn fmt_lines(changes: &mut ChangeSet) {
                     line_len -= b - lw;
                 }
                 // Check for any line width errors we couldn't correct.
-                if line_len > MAX_WIDTH {
+                if line_len > config!(max_width) {
                     // TODO store the error rather than reporting immediately.
                     println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters",
-                             f, cur_line, MAX_WIDTH);
+                             f, cur_line, config!(max_width));
                 }
                 line_len = 0;
                 cur_line += 1;
@@ -200,7 +236,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls {
 
     fn no_input(&mut self,
                 _: &getopts::Matches,
-                _: &config::Options,
+                _: &rustc_config::Options,
                 _: &Option<PathBuf>,
                 _: &Option<PathBuf>,
                 _: &diagnostics::registry::Registry)
@@ -248,7 +284,14 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls {
     }
 }
 
-pub fn run(args: Vec<String>, write_mode: WriteMode) {
+// args are the arguments passed on the command line, generally passed through
+// to the compiler.
+// write_mode determines what happens to the result of running rustfmt, see
+// WriteMode.
+// default_config is a string of toml data to be used to configure rustfmt.
+pub fn run(args: Vec<String>, write_mode: WriteMode, default_config: &str) {
+    config::set_config(default_config);
+
     let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode };
     rustc_driver::run_compiler(&args, &mut call_ctxt);
 }
diff --git a/src/visitor.rs b/src/visitor.rs
index 3cc9b36222b..2aac931c4e6 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -14,7 +14,7 @@ use syntax::visit;
 
 use utils;
 
-use {IDEAL_WIDTH, MAX_WIDTH, TAB_SPACES, SKIP_ANNOTATION};
+use SKIP_ANNOTATION;
 use changes::ChangeSet;
 
 pub struct FmtVisitor<'a> {
@@ -32,7 +32,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
                self.codemap.lookup_char_pos(ex.span.hi));
         self.format_missing(ex.span.lo);
         let offset = self.changes.cur_offset_span(ex.span);
-        let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset);
+        let new_str = self.rewrite_expr(ex, config!(max_width) - offset, offset);
         self.changes.push_str_span(ex.span, &new_str);
         self.last_pos = ex.span.hi;
     }
@@ -65,7 +65,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
 
         self.changes.push_str_span(b.span, "{");
         self.last_pos = self.last_pos + BytePos(1);
-        self.block_indent += TAB_SPACES;
+        self.block_indent += config!(tab_spaces);
 
         for stmt in &b.stmts {
             self.visit_stmt(&stmt)
@@ -78,7 +78,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
             None => {}
         }
 
-        self.block_indent -= TAB_SPACES;
+        self.block_indent -= config!(tab_spaces);
         // TODO we should compress any newlines here to just one
         self.format_missing_with_indent(b.span.hi - BytePos(1));
         self.changes.push_str_span(b.span, "}");
@@ -149,8 +149,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
                 match vp.node {
                     ast::ViewPath_::ViewPathList(ref path, ref path_list) => {
                         let block_indent = self.block_indent;
-                        let one_line_budget = MAX_WIDTH - block_indent;
-                        let multi_line_budget = IDEAL_WIDTH - block_indent;
+                        let one_line_budget = config!(max_width) - block_indent;
+                        let multi_line_budget = config!(ideal_width) - block_indent;
                         let new_str = self.rewrite_use_list(block_indent,
                                                             one_line_budget,
                                                             multi_line_budget,
@@ -170,9 +170,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
             ast::Item_::ItemImpl(..) |
             ast::Item_::ItemMod(_) |
             ast::Item_::ItemTrait(..) => {
-                self.block_indent += TAB_SPACES;
+                self.block_indent += config!(tab_spaces);
                 visit::walk_item(self, item);
-                self.block_indent -= TAB_SPACES;
+                self.block_indent -= config!(tab_spaces);
             }
             ast::Item_::ItemExternCrate(_) => {
                 self.format_missing_with_indent(item.span.lo);