Replace lone carriage returns with newlines

This commit is contained in:
Antonio Scandurra 2022-07-06 11:00:56 +02:00
parent 113eb9b94f
commit 13c9b1778b
4 changed files with 28 additions and 9 deletions

1
Cargo.lock generated
View file

@ -4910,6 +4910,7 @@ dependencies = [
"parking_lot 0.11.2", "parking_lot 0.11.2",
"postage", "postage",
"rand 0.8.5", "rand 0.8.5",
"regex",
"smallvec", "smallvec",
"sum_tree", "sum_tree",
"util", "util",

View file

@ -23,6 +23,7 @@ log = { version = "0.4.16", features = ["kv_unstable_serde"] }
parking_lot = "0.11" parking_lot = "0.11"
postage = { version = "0.4.1", features = ["futures-traits"] } postage = { version = "0.4.1", features = ["futures-traits"] }
rand = { version = "0.8.3", optional = true } rand = { version = "0.8.3", optional = true }
regex = "1.5"
smallvec = { version = "1.6", features = ["union"] } smallvec = { version = "1.6", features = ["union"] }
[dev-dependencies] [dev-dependencies]

View file

@ -43,7 +43,7 @@ fn test_random_edits(mut rng: StdRng) {
.take(reference_string_len) .take(reference_string_len)
.collect::<String>(); .collect::<String>();
let mut buffer = Buffer::new(0, 0, reference_string.clone().into()); let mut buffer = Buffer::new(0, 0, reference_string.clone().into());
reference_string = reference_string.replace("\r", ""); LineEnding::strip_carriage_returns(&mut reference_string);
buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200)); buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200));
let mut buffer_versions = Vec::new(); let mut buffer_versions = Vec::new();
@ -58,7 +58,6 @@ fn test_random_edits(mut rng: StdRng) {
for (old_range, new_text) in edits.iter().rev() { for (old_range, new_text) in edits.iter().rev() {
reference_string.replace_range(old_range.clone(), &new_text); reference_string.replace_range(old_range.clone(), &new_text);
} }
reference_string = reference_string.replace("\r", "");
assert_eq!(buffer.text(), reference_string); assert_eq!(buffer.text(), reference_string);
log::info!( log::info!(
@ -165,14 +164,14 @@ fn test_line_endings() {
LineEnding::Windows LineEnding::Windows
); );
let mut buffer = Buffer::new(0, 0, "one\r\ntwo".into()); let mut buffer = Buffer::new(0, 0, "one\r\ntwo\rthree".into());
assert_eq!(buffer.text(), "one\ntwo"); assert_eq!(buffer.text(), "one\ntwo\nthree");
assert_eq!(buffer.line_ending(), LineEnding::Windows); assert_eq!(buffer.line_ending(), LineEnding::Windows);
buffer.check_invariants(); buffer.check_invariants();
buffer.edit([(buffer.len()..buffer.len(), "\r\nthree")]); buffer.edit([(buffer.len()..buffer.len(), "\r\nfour")]);
buffer.edit([(0..0, "zero\r\n")]); buffer.edit([(0..0, "zero\r\n")]);
assert_eq!(buffer.text(), "zero\none\ntwo\nthree"); assert_eq!(buffer.text(), "zero\none\ntwo\nthree\nfour");
assert_eq!(buffer.line_ending(), LineEnding::Windows); assert_eq!(buffer.line_ending(), LineEnding::Windows);
buffer.check_invariants(); buffer.check_invariants();
} }

View file

@ -18,6 +18,7 @@ pub use anchor::*;
use anyhow::Result; use anyhow::Result;
use clock::ReplicaId; use clock::ReplicaId;
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};
use lazy_static::lazy_static;
use locator::Locator; use locator::Locator;
use operation_queue::OperationQueue; use operation_queue::OperationQueue;
pub use patch::Patch; pub use patch::Patch;
@ -26,10 +27,12 @@ pub use point_utf16::*;
use postage::{barrier, oneshot, prelude::*}; use postage::{barrier, oneshot, prelude::*};
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
pub use random_char_iter::*; pub use random_char_iter::*;
use regex::Regex;
use rope::TextDimension; use rope::TextDimension;
pub use rope::{Chunks, Rope, TextSummary}; pub use rope::{Chunks, Rope, TextSummary};
pub use selection::*; pub use selection::*;
use std::{ use std::{
borrow::Cow,
cmp::{self, Ordering}, cmp::{self, Ordering},
future::Future, future::Future,
iter::Iterator, iter::Iterator,
@ -42,6 +45,10 @@ pub use subscription::*;
pub use sum_tree::Bias; pub use sum_tree::Bias;
use sum_tree::{FilterCursor, SumTree}; use sum_tree::{FilterCursor, SumTree};
lazy_static! {
static ref CARRIAGE_RETURNS_REGEX: Regex = Regex::new("\r\n|\r").unwrap();
}
pub type TransactionId = clock::Local; pub type TransactionId = clock::Local;
pub struct Buffer { pub struct Buffer {
@ -1472,6 +1479,15 @@ impl Buffer {
log::info!("mutating buffer {} with {:?}", self.replica_id, edits); log::info!("mutating buffer {} with {:?}", self.replica_id, edits);
let op = self.edit(edits.iter().cloned()); let op = self.edit(edits.iter().cloned());
if let Operation::Edit(edit) = &op {
assert_eq!(edits.len(), edit.new_text.len());
for (edit, new_text) in edits.iter_mut().zip(&edit.new_text) {
edit.1 = new_text.clone();
}
} else {
unreachable!()
}
(edits, op) (edits, op)
} }
@ -2370,12 +2386,14 @@ impl LineEnding {
} }
pub fn strip_carriage_returns(text: &mut String) { pub fn strip_carriage_returns(text: &mut String) {
text.retain(|c| c != '\r') if let Cow::Owned(replaced) = CARRIAGE_RETURNS_REGEX.replace_all(text, "\n") {
*text = replaced;
}
} }
fn strip_carriage_returns_from_arc(text: Arc<str>) -> Arc<str> { fn strip_carriage_returns_from_arc(text: Arc<str>) -> Arc<str> {
if text.contains('\r') { if let Cow::Owned(replaced) = CARRIAGE_RETURNS_REGEX.replace_all(&text, "\n") {
text.replace('\r', "").into() replaced.into()
} else { } else {
text text
} }