Merge pull request #769 from svmnotn/write-mode-config
Allow for setting of write-mode via config file. FIxes #215
This commit is contained in:
commit
3f7741bb0c
7 changed files with 100 additions and 108 deletions
|
@ -17,8 +17,8 @@ extern crate toml;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
|
|
||||||
use rustfmt::{WriteMode, run, run_from_stdin};
|
use rustfmt::{run, run_from_stdin};
|
||||||
use rustfmt::config::Config;
|
use rustfmt::config::{Config, WriteMode};
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
|
@ -216,7 +216,7 @@ fn determine_operation(matches: &Matches) -> Operation {
|
||||||
Err(..) => return Operation::InvalidInput("Unrecognized write mode".into()),
|
Err(..) => return Operation::InvalidInput("Unrecognized write mode".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => WriteMode::Replace,
|
None => WriteMode::Default,
|
||||||
};
|
};
|
||||||
|
|
||||||
let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect();
|
let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect();
|
||||||
|
|
|
@ -120,6 +120,24 @@ configuration_option_enum! { ReportTactic:
|
||||||
Never,
|
Never,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configuration_option_enum! { WriteMode:
|
||||||
|
// Used internally to represent when no option is given
|
||||||
|
// Treated as Replace.
|
||||||
|
Default,
|
||||||
|
// Backsup the original file and overwrites the orignal.
|
||||||
|
Replace,
|
||||||
|
// Overwrites original file without backup.
|
||||||
|
Overwrite,
|
||||||
|
// Write the output to stdout.
|
||||||
|
Display,
|
||||||
|
// Write the diff to stdout.
|
||||||
|
Diff,
|
||||||
|
// Display how much of the input file was processed
|
||||||
|
Coverage,
|
||||||
|
// Unfancy stdout
|
||||||
|
Plain,
|
||||||
|
}
|
||||||
|
|
||||||
// This trait and the following impl blocks are there so that we an use
|
// This trait and the following impl blocks are there so that we an use
|
||||||
// UCFS inside the get_docs() function on types for configs.
|
// UCFS inside the get_docs() function on types for configs.
|
||||||
pub trait ConfigType {
|
pub trait ConfigType {
|
||||||
|
@ -323,4 +341,6 @@ create_config! {
|
||||||
match_block_trailing_comma: bool, false,
|
match_block_trailing_comma: bool, false,
|
||||||
"Put a trailing comma after a block based match arm (non-block arms are not affected)";
|
"Put a trailing comma after a block based match arm (non-block arms are not affected)";
|
||||||
match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm";
|
match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm";
|
||||||
|
write_mode: WriteMode, WriteMode::Default,
|
||||||
|
"What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage";
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,9 @@ use strings::string_buffer::StringBuffer;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::{self, Write, Read, stdout};
|
use std::io::{self, Write, Read, stdout, BufWriter};
|
||||||
|
|
||||||
use WriteMode;
|
use config::{NewlineStyle, Config, WriteMode};
|
||||||
use config::{NewlineStyle, Config};
|
|
||||||
use rustfmt_diff::{make_diff, print_diff};
|
use rustfmt_diff::{make_diff, print_diff};
|
||||||
|
|
||||||
// A map of the files of a crate, with their new content
|
// A map of the files of a crate, with their new content
|
||||||
|
@ -34,16 +33,48 @@ pub fn append_newlines(file_map: &mut FileMap) {
|
||||||
pub fn write_all_files(file_map: &FileMap,
|
pub fn write_all_files(file_map: &FileMap,
|
||||||
mode: WriteMode,
|
mode: WriteMode,
|
||||||
config: &Config)
|
config: &Config)
|
||||||
-> Result<(HashMap<String, String>), io::Error> {
|
-> Result<(), io::Error> {
|
||||||
let mut result = HashMap::new();
|
|
||||||
for filename in file_map.keys() {
|
for filename in file_map.keys() {
|
||||||
let one_result = try!(write_file(&file_map[filename], filename, mode, config));
|
try!(write_file(&file_map[filename], filename, mode, config));
|
||||||
if let Some(r) = one_result {
|
|
||||||
result.insert(filename.clone(), r);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints all newlines either as `\n` or as `\r\n`.
|
||||||
|
pub fn write_system_newlines<T>(writer: T,
|
||||||
|
text: &StringBuffer,
|
||||||
|
config: &Config)
|
||||||
|
-> Result<(), io::Error>
|
||||||
|
where T: Write
|
||||||
|
{
|
||||||
|
// Buffer output, since we're writing a since char at a time.
|
||||||
|
let mut writer = BufWriter::new(writer);
|
||||||
|
|
||||||
|
let style = if config.newline_style == NewlineStyle::Native {
|
||||||
|
if cfg!(windows) {
|
||||||
|
NewlineStyle::Windows
|
||||||
|
} else {
|
||||||
|
NewlineStyle::Unix
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config.newline_style
|
||||||
|
};
|
||||||
|
|
||||||
|
match style {
|
||||||
|
NewlineStyle::Unix => write!(writer, "{}", text),
|
||||||
|
NewlineStyle::Windows => {
|
||||||
|
for (c, _) in text.chars() {
|
||||||
|
match c {
|
||||||
|
'\n' => try!(write!(writer, "\r\n")),
|
||||||
|
'\r' => continue,
|
||||||
|
c => try!(write!(writer, "{}", c)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
NewlineStyle::Native => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_file(text: &StringBuffer,
|
pub fn write_file(text: &StringBuffer,
|
||||||
|
@ -52,39 +83,6 @@ pub fn write_file(text: &StringBuffer,
|
||||||
config: &Config)
|
config: &Config)
|
||||||
-> Result<Option<String>, io::Error> {
|
-> Result<Option<String>, io::Error> {
|
||||||
|
|
||||||
// prints all newlines either as `\n` or as `\r\n`
|
|
||||||
fn write_system_newlines<T>(mut writer: T,
|
|
||||||
text: &StringBuffer,
|
|
||||||
config: &Config)
|
|
||||||
-> Result<(), io::Error>
|
|
||||||
where T: Write
|
|
||||||
{
|
|
||||||
let style = if config.newline_style == NewlineStyle::Native {
|
|
||||||
if cfg!(windows) {
|
|
||||||
NewlineStyle::Windows
|
|
||||||
} else {
|
|
||||||
NewlineStyle::Unix
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
config.newline_style
|
|
||||||
};
|
|
||||||
|
|
||||||
match style {
|
|
||||||
NewlineStyle::Unix => write!(writer, "{}", text),
|
|
||||||
NewlineStyle::Windows => {
|
|
||||||
for (c, _) in text.chars() {
|
|
||||||
match c {
|
|
||||||
'\n' => try!(write!(writer, "\r\n")),
|
|
||||||
'\r' => continue,
|
|
||||||
c => try!(write!(writer, "{}", c)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
NewlineStyle::Native => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn source_and_formatted_text(text: &StringBuffer,
|
fn source_and_formatted_text(text: &StringBuffer,
|
||||||
filename: &str,
|
filename: &str,
|
||||||
config: &Config)
|
config: &Config)
|
||||||
|
@ -123,11 +121,6 @@ pub fn write_file(text: &StringBuffer,
|
||||||
let file = try!(File::create(filename));
|
let file = try!(File::create(filename));
|
||||||
try!(write_system_newlines(file, text, config));
|
try!(write_system_newlines(file, text, config));
|
||||||
}
|
}
|
||||||
WriteMode::NewFile(extn) => {
|
|
||||||
let filename = filename.to_owned() + "." + extn;
|
|
||||||
let file = try!(File::create(&filename));
|
|
||||||
try!(write_system_newlines(file, text, config));
|
|
||||||
}
|
|
||||||
WriteMode::Plain => {
|
WriteMode::Plain => {
|
||||||
let stdout = stdout();
|
let stdout = stdout();
|
||||||
let stdout = stdout.lock();
|
let stdout = stdout.lock();
|
||||||
|
@ -146,13 +139,8 @@ pub fn write_file(text: &StringBuffer,
|
||||||
|line_num| format!("\nDiff at line {}:", line_num));
|
|line_num| format!("\nDiff at line {}:", line_num));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WriteMode::Return => {
|
WriteMode::Default => {
|
||||||
// io::Write is not implemented for String, working around with
|
unreachable!("The WriteMode should NEVER Be default at this point!");
|
||||||
// Vec<u8>
|
|
||||||
let mut v = Vec::new();
|
|
||||||
try!(write_system_newlines(&mut v, text, config));
|
|
||||||
// won't panic, we are writing correct utf8
|
|
||||||
return Ok(Some(String::from_utf8(v).unwrap()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
57
src/lib.rs
57
src/lib.rs
|
@ -34,12 +34,11 @@ use std::ops::{Add, Sub};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use issues::{BadIssueSeeker, Issue};
|
use issues::{BadIssueSeeker, Issue};
|
||||||
use filemap::FileMap;
|
use filemap::FileMap;
|
||||||
use visitor::FmtVisitor;
|
use visitor::FmtVisitor;
|
||||||
use config::Config;
|
use config::{Config, WriteMode};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod utils;
|
mod utils;
|
||||||
|
@ -187,42 +186,6 @@ impl Sub<usize> for Indent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub enum WriteMode {
|
|
||||||
// Backsup the original file and overwrites the orignal.
|
|
||||||
Replace,
|
|
||||||
// Overwrites original file without backup.
|
|
||||||
Overwrite,
|
|
||||||
// str is the extension of the new file.
|
|
||||||
NewFile(&'static str),
|
|
||||||
// Write the output to stdout.
|
|
||||||
Display,
|
|
||||||
// Write the diff to stdout.
|
|
||||||
Diff,
|
|
||||||
// Return the result as a mapping from filenames to Strings.
|
|
||||||
Return,
|
|
||||||
// Display how much of the input file was processed
|
|
||||||
Coverage,
|
|
||||||
// Unfancy stdout
|
|
||||||
Plain,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for WriteMode {
|
|
||||||
type Err = ();
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
match s {
|
|
||||||
"replace" => Ok(WriteMode::Replace),
|
|
||||||
"display" => Ok(WriteMode::Display),
|
|
||||||
"overwrite" => Ok(WriteMode::Overwrite),
|
|
||||||
"diff" => Ok(WriteMode::Diff),
|
|
||||||
"coverage" => Ok(WriteMode::Coverage),
|
|
||||||
"plain" => Ok(WriteMode::Plain),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ErrorKind {
|
pub enum ErrorKind {
|
||||||
// Line has exceeded character limit
|
// Line has exceeded character limit
|
||||||
LineOverflow,
|
LineOverflow,
|
||||||
|
@ -445,16 +408,27 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap {
|
||||||
file_map
|
file_map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure that we are using the correct WriteMode,
|
||||||
|
// preferring what is passed as an argument
|
||||||
|
fn check_write_mode(arg: WriteMode, config: WriteMode) -> WriteMode {
|
||||||
|
match (arg, config) {
|
||||||
|
(WriteMode::Default, WriteMode::Default) => WriteMode::Replace,
|
||||||
|
(WriteMode::Default, mode) => mode,
|
||||||
|
(mode, _) => mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// args are the arguments passed on the command line, generally passed through
|
// args are the arguments passed on the command line, generally passed through
|
||||||
// to the compiler.
|
// to the compiler.
|
||||||
// write_mode determines what happens to the result of running rustfmt, see
|
// write_mode determines what happens to the result of running rustfmt, see
|
||||||
// WriteMode.
|
// WriteMode.
|
||||||
pub fn run(file: &Path, write_mode: WriteMode, config: &Config) {
|
pub fn run(file: &Path, write_mode: WriteMode, config: &Config) {
|
||||||
let mut result = format(file, config, write_mode);
|
let mode = check_write_mode(write_mode, config.write_mode);
|
||||||
|
let mut result = format(file, config, mode);
|
||||||
|
|
||||||
print!("{}", fmt_lines(&mut result, config));
|
print!("{}", fmt_lines(&mut result, config));
|
||||||
|
|
||||||
let write_result = filemap::write_all_files(&result, write_mode, config);
|
let write_result = filemap::write_all_files(&result, mode, config);
|
||||||
|
|
||||||
if let Err(msg) = write_result {
|
if let Err(msg) = write_result {
|
||||||
println!("Error writing files: {}", msg);
|
println!("Error writing files: {}", msg);
|
||||||
|
@ -462,7 +436,8 @@ pub fn run(file: &Path, write_mode: WriteMode, config: &Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Similar to run, but takes an input String instead of a file to format
|
// Similar to run, but takes an input String instead of a file to format
|
||||||
pub fn run_from_stdin(input: String, mode: WriteMode, config: &Config) {
|
pub fn run_from_stdin(input: String, write_mode: WriteMode, config: &Config) {
|
||||||
|
let mode = check_write_mode(write_mode, config.write_mode);
|
||||||
let mut result = format_string(input, config, mode);
|
let mut result = format_string(input, config, mode);
|
||||||
fmt_lines(&mut result, config);
|
fmt_lines(&mut result, config);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use WriteMode;
|
use config::WriteMode;
|
||||||
use visitor::FmtVisitor;
|
use visitor::FmtVisitor;
|
||||||
use syntax::codemap::{self, BytePos, Span, Pos};
|
use syntax::codemap::{self, BytePos, Span, Pos};
|
||||||
use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment};
|
use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment};
|
||||||
|
|
|
@ -15,9 +15,9 @@ use syntax::visit;
|
||||||
|
|
||||||
use strings::string_buffer::StringBuffer;
|
use strings::string_buffer::StringBuffer;
|
||||||
|
|
||||||
use {Indent, WriteMode};
|
use Indent;
|
||||||
use utils;
|
use utils;
|
||||||
use config::Config;
|
use config::{Config, WriteMode};
|
||||||
use rewrite::{Rewrite, RewriteContext};
|
use rewrite::{Rewrite, RewriteContext};
|
||||||
use comment::rewrite_comment;
|
use comment::rewrite_comment;
|
||||||
use macros::rewrite_macro;
|
use macros::rewrite_macro;
|
||||||
|
|
|
@ -19,7 +19,8 @@ use std::io::{self, Read, BufRead, BufReader};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use rustfmt::*;
|
use rustfmt::*;
|
||||||
use rustfmt::config::{Config, ReportTactic};
|
use rustfmt::filemap::write_system_newlines;
|
||||||
|
use rustfmt::config::{Config, ReportTactic, WriteMode};
|
||||||
use rustfmt::rustfmt_diff::*;
|
use rustfmt::rustfmt_diff::*;
|
||||||
|
|
||||||
static DIFF_CONTEXT_SIZE: usize = 3;
|
static DIFF_CONTEXT_SIZE: usize = 3;
|
||||||
|
@ -43,7 +44,7 @@ fn system_tests() {
|
||||||
// Turn a DirEntry into a String that represents the relative path to the
|
// Turn a DirEntry into a String that represents the relative path to the
|
||||||
// file.
|
// file.
|
||||||
let files = files.map(get_path_string);
|
let files = files.map(get_path_string);
|
||||||
let (_reports, count, fails) = check_files(files, WriteMode::Return);
|
let (_reports, count, fails) = check_files(files, WriteMode::Default);
|
||||||
|
|
||||||
// Display results.
|
// Display results.
|
||||||
println!("Ran {} system tests.", count);
|
println!("Ran {} system tests.", count);
|
||||||
|
@ -71,7 +72,7 @@ fn idempotence_tests() {
|
||||||
.ok()
|
.ok()
|
||||||
.expect("Couldn't read target dir.")
|
.expect("Couldn't read target dir.")
|
||||||
.map(get_path_string);
|
.map(get_path_string);
|
||||||
let (_reports, count, fails) = check_files(files, WriteMode::Return);
|
let (_reports, count, fails) = check_files(files, WriteMode::Default);
|
||||||
|
|
||||||
// Display results.
|
// Display results.
|
||||||
println!("Ran {} idempotent tests.", count);
|
println!("Ran {} idempotent tests.", count);
|
||||||
|
@ -90,7 +91,7 @@ fn self_tests() {
|
||||||
// Hack because there's no `IntoIterator` impl for `[T; N]`.
|
// Hack because there's no `IntoIterator` impl for `[T; N]`.
|
||||||
let files = files.chain(Some("src/lib.rs".to_owned()).into_iter());
|
let files = files.chain(Some("src/lib.rs".to_owned()).into_iter());
|
||||||
|
|
||||||
let (reports, count, fails) = check_files(files, WriteMode::Return);
|
let (reports, count, fails) = check_files(files, WriteMode::Default);
|
||||||
let mut warnings = 0;
|
let mut warnings = 0;
|
||||||
|
|
||||||
// Display results.
|
// Display results.
|
||||||
|
@ -162,8 +163,16 @@ pub fn idempotent_check(filename: String,
|
||||||
let mut file_map = format(Path::new(&filename), &config, write_mode);
|
let mut file_map = format(Path::new(&filename), &config, write_mode);
|
||||||
let format_report = fmt_lines(&mut file_map, &config);
|
let format_report = fmt_lines(&mut file_map, &config);
|
||||||
|
|
||||||
// Won't panic, as we're not doing any IO.
|
let mut write_result = HashMap::new();
|
||||||
let write_result = filemap::write_all_files(&file_map, WriteMode::Return, &config).unwrap();
|
for (filename, text) in file_map.iter() {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
// Won't panic, as we're not doing any IO.
|
||||||
|
write_system_newlines(&mut v, text, &config).unwrap();
|
||||||
|
// Won't panic, we are writing correct utf8.
|
||||||
|
let one_result = String::from_utf8(v).unwrap();
|
||||||
|
write_result.insert(filename.clone(), one_result);
|
||||||
|
}
|
||||||
|
|
||||||
let target = sig_comments.get("target").map(|x| &(*x)[..]);
|
let target = sig_comments.get("target").map(|x| &(*x)[..]);
|
||||||
|
|
||||||
handle_result(write_result, target, write_mode).map(|_| format_report)
|
handle_result(write_result, target, write_mode).map(|_| format_report)
|
||||||
|
|
Loading…
Reference in a new issue