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 c => transformed.push(c),
81 fn auto_detects_unix_newlines() {
83 EffectiveNewlineStyle::Unix,
84 auto_detect_newline_style("One\nTwo\nThree")
89 fn auto_detects_windows_newlines() {
91 EffectiveNewlineStyle::Windows,
92 auto_detect_newline_style("One\r\nTwo\r\nThree")
97 fn auto_detects_windows_newlines_with_multibyte_char_on_first_line() {
99 EffectiveNewlineStyle::Windows,
100 auto_detect_newline_style("A 🎢 of a first line\r\nTwo\r\nThree")
105 fn falls_back_to_native_newlines_if_no_newlines_are_found() {
106 let expected_newline_style = if cfg!(windows) {
107 EffectiveNewlineStyle::Windows
109 EffectiveNewlineStyle::Unix
112 expected_newline_style,
113 auto_detect_newline_style("One Two Three")
118 fn auto_detects_and_applies_unix_newlines() {
119 let formatted_text = "One\nTwo\nThree";
120 let raw_input_text = "One\nTwo\nThree";
122 let mut out = String::from(formatted_text);
123 apply_newline_style(NewlineStyle::Auto, &mut out, raw_input_text);
124 assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'");
128 fn auto_detects_and_applies_windows_newlines() {
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(NewlineStyle::Auto, &mut out, raw_input_text);
134 assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'");
138 fn auto_detects_and_applies_native_newlines() {
139 let formatted_text = "One\nTwo\nThree";
140 let raw_input_text = "One Two Three";
142 let mut out = String::from(formatted_text);
143 apply_newline_style(NewlineStyle::Auto, &mut out, raw_input_text);
147 "One\r\nTwo\r\nThree", &out,
148 "auto-native-windows should detect 'crlf'"
152 "One\nTwo\nThree", &out,
153 "auto-native-unix should detect 'lf'"
159 fn preserves_standalone_carriage_returns_when_applying_windows_newlines() {
160 let formatted_text = "One\nTwo\nThree\rDrei";
161 let raw_input_text = "One\nTwo\nThree\rDrei";
163 let mut out = String::from(formatted_text);
164 apply_newline_style(NewlineStyle::Windows, &mut out, raw_input_text);
166 assert_eq!("One\r\nTwo\r\nThree\rDrei", &out);
170 fn preserves_standalone_carriage_returns_when_applying_unix_newlines() {
171 let formatted_text = "One\nTwo\nThree\rDrei";
172 let raw_input_text = "One\nTwo\nThree\rDrei";
174 let mut out = String::from(formatted_text);
175 apply_newline_style(NewlineStyle::Unix, &mut out, raw_input_text);
177 assert_eq!("One\nTwo\nThree\rDrei", &out);