1 use crate::NewlineStyle;
3 /// Apply this newline style to the formatted text. When the style is set
4 /// to `Auto`, the `raw_input_text` is used to detect the existing line
7 /// If the style is set to `Auto` and `raw_input_text` contains no
8 /// newlines, the `Native` style will be used.
9 pub(crate) fn apply_newline_style(
10 newline_style: NewlineStyle,
11 formatted_text: &mut String,
14 match effective_newline_style(newline_style, raw_input_text) {
15 EffectiveNewlineStyle::Windows => {
16 *formatted_text = convert_to_windows_newlines(formatted_text);
18 EffectiveNewlineStyle::Unix => {}
22 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
23 enum EffectiveNewlineStyle {
28 fn effective_newline_style(
29 newline_style: NewlineStyle,
31 ) -> EffectiveNewlineStyle {
33 NewlineStyle::Auto => auto_detect_newline_style(raw_input_text),
34 NewlineStyle::Native => native_newline_style(),
35 NewlineStyle::Windows => EffectiveNewlineStyle::Windows,
36 NewlineStyle::Unix => EffectiveNewlineStyle::Unix,
40 const LINE_FEED: char = '\n';
41 const CARRIAGE_RETURN: char = '\r';
43 fn auto_detect_newline_style(raw_input_text: &str) -> EffectiveNewlineStyle {
44 if let Some(pos) = raw_input_text.chars().position(|ch| ch == LINE_FEED) {
45 let pos = pos.saturating_sub(1);
46 if let Some(CARRIAGE_RETURN) = raw_input_text.chars().nth(pos) {
47 EffectiveNewlineStyle::Windows
49 EffectiveNewlineStyle::Unix
52 native_newline_style()
56 fn native_newline_style() -> EffectiveNewlineStyle {
58 EffectiveNewlineStyle::Windows
60 EffectiveNewlineStyle::Unix
64 fn convert_to_windows_newlines(formatted_text: &String) -> String {
65 let mut transformed = String::with_capacity(2 * formatted_text.capacity());
66 for c in formatted_text.chars() {
67 const WINDOWS_NEWLINE: &str = "\r\n";
69 LINE_FEED => transformed.push_str(WINDOWS_NEWLINE),
70 CARRIAGE_RETURN => continue,
71 c => transformed.push(c),
82 fn auto_detects_unix_newlines() {
84 EffectiveNewlineStyle::Unix,
85 auto_detect_newline_style("One\nTwo\nThree")
90 fn auto_detects_windows_newlines() {
92 EffectiveNewlineStyle::Windows,
93 auto_detect_newline_style("One\r\nTwo\r\nThree")
98 fn auto_detects_windows_newlines_with_multibyte_char_on_first_line() {
100 EffectiveNewlineStyle::Windows,
101 auto_detect_newline_style("A 🎢 of a first line\r\nTwo\r\nThree")
106 fn falls_back_to_native_newlines_if_no_newlines_are_found() {
107 let expected_newline_style = if cfg!(windows) {
108 EffectiveNewlineStyle::Windows
110 EffectiveNewlineStyle::Unix
113 expected_newline_style,
114 auto_detect_newline_style("One Two Three")
119 fn test_newline_style_auto_apply() {
120 let auto = NewlineStyle::Auto;
122 let formatted_text = "One\nTwo\nThree";
123 let raw_input_text = "One\nTwo\nThree";
125 let mut out = String::from(formatted_text);
126 apply_newline_style(auto, &mut out, raw_input_text);
127 assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'");
129 let formatted_text = "One\nTwo\nThree";
130 let raw_input_text = "One\r\nTwo\r\nThree";
132 let mut out = String::from(formatted_text);
133 apply_newline_style(auto, &mut out, raw_input_text);
134 assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'");
138 let formatted_text = "One\nTwo\nThree";
139 let raw_input_text = "One Two Three";
141 let mut out = String::from(formatted_text);
142 apply_newline_style(auto, &mut out, raw_input_text);
144 "One\nTwo\nThree", &out,
145 "auto-native-unix should detect 'lf'"
151 let formatted_text = "One\nTwo\nThree";
152 let raw_input_text = "One Two Three";
154 let mut out = String::from(formatted_text);
155 apply_newline_style(auto, &mut out, raw_input_text);
157 "One\r\nTwo\r\nThree", &out,
158 "auto-native-windows should detect 'crlf'"