From 1655583b02578150d2ef08e16bda0c8bfe8194aa Mon Sep 17 00:00:00 2001
From: Oliver Schneider <git1984941651981@oli-obk.de>
Date: Thu, 30 Apr 2015 13:13:20 +0200
Subject: [PATCH] handle windows newlines

---
 src/changes.rs | 44 +++++++++++++++++++++++++++++++++++++-------
 src/lib.rs     |  7 +++++++
 2 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/src/changes.rs b/src/changes.rs
index 8884b05d77e..f0aebe7c94f 100644
--- a/src/changes.rs
+++ b/src/changes.rs
@@ -18,8 +18,10 @@ use std::collections::HashMap;
 use syntax::codemap::{CodeMap, Span, BytePos};
 use std::fmt;
 use std::fs::File;
-use std::io::Write;
+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
 // to work with libsyntax. It is badly named.
@@ -148,6 +150,28 @@ impl<'a> ChangeSet<'a> {
                       -> Result<Option<String>, ::std::io::Error> {
         let text = &self.file_map[filename];
 
+        // prints all newlines either as `\n` or as `\r\n`
+        fn write_system_newlines<T>(
+            mut writer: T,
+            text: &StringBuffer)
+            -> Result<(), ::std::io::Error>
+            where T: Write,
+        {
+            match NEWLINE_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(())
+                },
+            }
+        }
+
         match mode {
             WriteMode::Overwrite => {
                 // Do a little dance to make writing safer - write to a temp file
@@ -157,8 +181,8 @@ impl<'a> ChangeSet<'a> {
                 let bk_name = filename.to_owned() + ".bk";
                 {
                     // Write text to temp file
-                    let mut tmp_file = try!(File::create(&tmp_name));
-                    try!(write!(tmp_file, "{}", text));
+                    let tmp_file = try!(File::create(&tmp_name));
+                    try!(write_system_newlines(tmp_file, text));
                 }
 
                 try!(::std::fs::rename(filename, bk_name));
@@ -166,15 +190,21 @@ impl<'a> ChangeSet<'a> {
             }
             WriteMode::NewFile(extn) => {
                 let filename = filename.to_owned() + "." + extn;
-                let mut file = try!(File::create(&filename));
-                try!(write!(file, "{}", text));
+                let file = try!(File::create(&filename));
+                try!(write_system_newlines(file, text));
             }
             WriteMode::Display => {
                 println!("{}:\n", filename);
-                println!("{}", text);
+                let stdout = stdout();
+                let stdout_lock = stdout.lock();
+                try!(write_system_newlines(stdout_lock, text));
             }
             WriteMode::Return(_) => {
-                return Ok(Some(text.to_string()));
+                // io::Write is not implemented for String, working around with Vec<u8>
+                let mut v = Vec::new();
+                try!(write_system_newlines(&mut v, text));
+                // won't panic, we are writing correct utf8
+                return Ok(Some(String::from_utf8(v).unwrap()));
             }
         }
 
diff --git a/src/lib.rs b/src/lib.rs
index e22a0861390..cf191f04f95 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -59,6 +59,7 @@ 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.
@@ -75,6 +76,12 @@ pub enum WriteMode {
     Return(&'static Fn(HashMap<String, String>)),
 }
 
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+enum NewlineStyle {
+    Windows, // \r\n
+    Unix, // \n
+}
+
 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
 enum BraceStyle {
     AlwaysNextLine,