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 *formatted_text
= match effective_newline_style(newline_style
, raw_input_text
) {
15 EffectiveNewlineStyle
::Windows
=> convert_to_windows_newlines(formatted_text
),
16 EffectiveNewlineStyle
::Unix
=> convert_to_unix_newlines(formatted_text
),
20 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
21 enum EffectiveNewlineStyle
{
26 fn effective_newline_style(
27 newline_style
: NewlineStyle
,
29 ) -> EffectiveNewlineStyle
{
31 NewlineStyle
::Auto
=> auto_detect_newline_style(raw_input_text
),
32 NewlineStyle
::Native
=> native_newline_style(),
33 NewlineStyle
::Windows
=> EffectiveNewlineStyle
::Windows
,
34 NewlineStyle
::Unix
=> EffectiveNewlineStyle
::Unix
,
38 const LINE_FEED
: char = '
\n'
;
39 const CARRIAGE_RETURN
: char = '
\r'
;
40 const WINDOWS_NEWLINE
: &str = "\r\n";
41 const UNIX_NEWLINE
: &str = "\n";
43 fn auto_detect_newline_style(raw_input_text
: &str) -> EffectiveNewlineStyle
{
44 let first_line_feed_pos
= raw_input_text
.chars().position(|ch
| ch
== LINE_FEED
);
45 match first_line_feed_pos
{
46 Some(first_line_feed_pos
) => {
47 let char_before_line_feed_pos
= first_line_feed_pos
.saturating_sub(1);
48 let char_before_line_feed
= raw_input_text
.chars().nth(char_before_line_feed_pos
);
49 match char_before_line_feed
{
50 Some(CARRIAGE_RETURN
) => EffectiveNewlineStyle
::Windows
,
51 _
=> EffectiveNewlineStyle
::Unix
,
54 None
=> native_newline_style(),
58 fn native_newline_style() -> EffectiveNewlineStyle
{
60 EffectiveNewlineStyle
::Windows
62 EffectiveNewlineStyle
::Unix
66 fn convert_to_windows_newlines(formatted_text
: &String
) -> String
{
67 let mut transformed
= String
::with_capacity(2 * formatted_text
.capacity());
68 let mut chars
= formatted_text
.chars().peekable();
69 while let Some(current_char
) = chars
.next() {
70 let next_char
= chars
.peek();
72 LINE_FEED
=> transformed
.push_str(WINDOWS_NEWLINE
),
73 CARRIAGE_RETURN
if next_char
== Some(&LINE_FEED
) => {}
74 current_char
=> transformed
.push(current_char
),
80 fn convert_to_unix_newlines(formatted_text
: &String
) -> String
{
81 formatted_text
.replace(WINDOWS_NEWLINE
, UNIX_NEWLINE
)
89 fn auto_detects_unix_newlines() {
91 EffectiveNewlineStyle
::Unix
,
92 auto_detect_newline_style("One\nTwo\nThree")
97 fn auto_detects_windows_newlines() {
99 EffectiveNewlineStyle
::Windows
,
100 auto_detect_newline_style("One\r\nTwo\r\nThree")
105 fn auto_detects_windows_newlines_with_multibyte_char_on_first_line() {
107 EffectiveNewlineStyle
::Windows
,
108 auto_detect_newline_style("A 🎢 of a first line\r\nTwo\r\nThree")
113 fn falls_back_to_native_newlines_if_no_newlines_are_found() {
114 let expected_newline_style
= if cfg
!(windows
) {
115 EffectiveNewlineStyle
::Windows
117 EffectiveNewlineStyle
::Unix
120 expected_newline_style
,
121 auto_detect_newline_style("One Two Three")
126 fn auto_detects_and_applies_unix_newlines() {
127 let formatted_text
= "One\nTwo\nThree";
128 let raw_input_text
= "One\nTwo\nThree";
130 let mut out
= String
::from(formatted_text
);
131 apply_newline_style(NewlineStyle
::Auto
, &mut out
, raw_input_text
);
132 assert_eq
!("One\nTwo\nThree", &out
, "auto should detect 'lf'");
136 fn auto_detects_and_applies_windows_newlines() {
137 let formatted_text
= "One\nTwo\nThree";
138 let raw_input_text
= "One\r\nTwo\r\nThree";
140 let mut out
= String
::from(formatted_text
);
141 apply_newline_style(NewlineStyle
::Auto
, &mut out
, raw_input_text
);
142 assert_eq
!("One\r\nTwo\r\nThree", &out
, "auto should detect 'crlf'");
146 fn auto_detects_and_applies_native_newlines() {
147 let formatted_text
= "One\nTwo\nThree";
148 let raw_input_text
= "One Two Three";
150 let mut out
= String
::from(formatted_text
);
151 apply_newline_style(NewlineStyle
::Auto
, &mut out
, raw_input_text
);
155 "One\r\nTwo\r\nThree", &out
,
156 "auto-native-windows should detect 'crlf'"
160 "One\nTwo\nThree", &out
,
161 "auto-native-unix should detect 'lf'"
167 fn applies_unix_newlines() {
168 test_newlines_are_applied_correctly(
176 fn applying_unix_newlines_changes_nothing_for_unix_newlines() {
177 let formatted_text
= "One\nTwo\nThree";
178 test_newlines_are_applied_correctly(formatted_text
, formatted_text
, NewlineStyle
::Unix
);
182 fn applies_unix_newlines_to_string_with_unix_and_windows_newlines() {
183 test_newlines_are_applied_correctly(
184 "One\r\nTwo\r\nThree\nFour",
185 "One\nTwo\nThree\nFour",
191 fn applies_windows_newlines_to_string_with_unix_and_windows_newlines() {
192 test_newlines_are_applied_correctly(
193 "One\nTwo\nThree\r\nFour",
194 "One\r\nTwo\r\nThree\r\nFour",
195 NewlineStyle
::Windows
,
200 fn applying_windows_newlines_changes_nothing_for_windows_newlines() {
201 let formatted_text
= "One\r\nTwo\r\nThree";
202 test_newlines_are_applied_correctly(formatted_text
, formatted_text
, NewlineStyle
::Windows
);
206 fn keeps_carriage_returns_when_applying_windows_newlines_to_str_with_unix_newlines() {
207 test_newlines_are_applied_correctly(
208 "One\nTwo\nThree\rDrei",
209 "One\r\nTwo\r\nThree\rDrei",
210 NewlineStyle
::Windows
,
215 fn keeps_carriage_returns_when_applying_unix_newlines_to_str_with_unix_newlines() {
216 test_newlines_are_applied_correctly(
217 "One\nTwo\nThree\rDrei",
218 "One\nTwo\nThree\rDrei",
224 fn keeps_carriage_returns_when_applying_windows_newlines_to_str_with_windows_newlines() {
225 test_newlines_are_applied_correctly(
226 "One\r\nTwo\r\nThree\rDrei",
227 "One\r\nTwo\r\nThree\rDrei",
228 NewlineStyle
::Windows
,
233 fn keeps_carriage_returns_when_applying_unix_newlines_to_str_with_windows_newlines() {
234 test_newlines_are_applied_correctly(
235 "One\r\nTwo\r\nThree\rDrei",
236 "One\nTwo\nThree\rDrei",
241 fn test_newlines_are_applied_correctly(
244 newline_style
: NewlineStyle
,
246 let mut out
= String
::from(input
);
247 apply_newline_style(newline_style
, &mut out
, input
);
248 assert_eq
!(expected
, &out
);