diff --git a/helix-core/src/line_ending.rs b/helix-core/src/line_ending.rs index 4f5708ec..f9d67b57 100644 --- a/helix-core/src/line_ending.rs +++ b/helix-core/src/line_ending.rs @@ -13,6 +13,29 @@ pub enum LineEnding { PS, // U+2029 -- ParagraphSeparator } +impl LineEnding { + pub fn len(&self) -> usize { + match self { + Self::Crlf => 2, + _ => 1, + } + } + + pub fn as_str(&self) -> &str { + match self { + Self::Crlf => "\u{000D}\u{000A}", + Self::LF => "\u{000A}", + Self::Nel => "\u{0085}", + Self::LS => "\u{2028}", + Self::CR => "\u{000D}", + _ => panic!( + "Unexpected line ending: {:?}, expected Crlf, LF, CR, Nel, or LS.", + self + ), + } + } +} + pub fn rope_slice_to_line_ending(g: &RopeSlice) -> Option { if let Some(text) = g.as_str() { str_to_line_ending(text) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 644c2e23..62faadf9 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -184,14 +184,10 @@ pub fn move_line_end(cx: &mut Context) { let line = text.char_to_line(range.head); // Line end is pos at the start of next line - 1 - // subtract 3 if the line ending is \r\n, otherwise subtract 2 as I assume all others are just 1 char length - let pos = - text.line_to_char(line + 1) - .saturating_sub(if doc.line_ending == LineEnding::Crlf { - 3 - } else { - 2 - }); + // subtract another 1 because the line ends with \n + let pos = text + .line_to_char(line + 1) + .saturating_sub(doc.line_ending().len() + 1); Range::new(pos, pos) }); @@ -612,14 +608,10 @@ pub fn extend_line_end(cx: &mut Context) { let line = text.char_to_line(range.head); // Line end is pos at the start of next line - 1 - // subtract 3 if the line ending is \r\n, otherwise subtract 2 as I assume all others are just 1 char length - let pos = - text.line_to_char(line + 1) - .saturating_sub(if doc.line_ending == LineEnding::Crlf { - 3 - } else { - 2 - }); + // subtract another 1 because the line ends with \n + let pos = text + .line_to_char(line + 1) + .saturating_sub(doc.line_ending().len() + 1); Range::new(range.anchor, pos) }); @@ -908,7 +900,7 @@ pub fn append_mode(cx: &mut Context) { if selection.iter().any(|range| range.head == end) { let transaction = Transaction::change( doc.text(), - std::array::IntoIter::new([(end, end, Some(Tendril::from_char('\n')))]), // TODO: change \n to doc.line_ending() + std::array::IntoIter::new([(end, end, Some(doc.line_ending().as_str().into()))]), ); doc.apply(&transaction, view.id); } @@ -1535,7 +1527,7 @@ fn open(cx: &mut Context, open: Open) { ); let indent = doc.indent_unit().repeat(indent_level); let mut text = String::with_capacity(1 + indent.len()); - text.push_str(doc.line_ending()); + text.push_str(doc.line_ending().as_str()); text.push_str(&indent); let text = text.repeat(count); @@ -2143,7 +2135,7 @@ pub mod insert { ); let indent = doc.indent_unit().repeat(indent_level); let mut text = String::with_capacity(1 + indent.len()); - text.push_str(doc.line_ending()); + text.push_str(doc.line_ending().as_str()); text.push_str(&indent); let head = pos + offs + text.chars().count(); @@ -2164,7 +2156,7 @@ pub mod insert { if helix_core::auto_pairs::PAIRS.contains(&(prev, curr)) { // another newline, indent the end bracket one level less let indent = doc.indent_unit().repeat(indent_level.saturating_sub(1)); - text.push_str(doc.line_ending()); + text.push_str(doc.line_ending().as_str()); text.push_str(&indent); } @@ -2283,7 +2275,7 @@ fn paste_impl( // if any of values ends \n it's linewise paste let linewise = values .iter() - .any(|value| value.ends_with(doc.line_ending())); + .any(|value| value.ends_with(doc.line_ending().as_str())); let mut values = values.iter().cloned().map(Tendril::from).chain(repeat); diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index bf26d8a0..fe06d09d 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -63,7 +63,7 @@ pub struct Document { diagnostics: Vec, language_server: Option>, - pub line_ending: LineEnding, + line_ending: LineEnding, } use std::fmt; @@ -728,18 +728,8 @@ impl Document { self.diagnostics = diagnostics; } - pub fn line_ending(&self) -> &'static str { - match self.line_ending { - LineEnding::Crlf => "\u{000D}\u{000A}", - LineEnding::LF => "\u{000A}", - LineEnding::Nel => "\u{0085}", - LineEnding::LS => "\u{2028}", - LineEnding::CR => "\u{000D}", - _ => panic!( - "Unexpected line ending: {:?}, expected Crlf, LF, CR, Nel, or LS.", - self.line_ending - ), - } + pub fn line_ending(&self) -> LineEnding { + self.line_ending } }