on master help sign in
added get_line_ending from pr comment
commitecb884db98fbe6ed70743d1080ce7f78e121ba50 authorJan Hrastnik <jan.hrastnik2@gmail.com> dateSat 19 Jun 2021, 14:03 (5 years ago) parent8bccd6d
3 files changed+24−13
helix-core/src/lib.rs+1−1 helix-core/src/line_ending.rs+18−5 helix-term/src/commands.rs+5−7
helix-core/src/lib.rs+1−1
@@ -111,6 +111,6 @@ pub use diagnostic::Diagnostic;
111111pub use state::State;
112112
113113pub use line_ending::{
114− auto_detect_line_ending, rope_slice_to_line_ending, LineEnding, DEFAULT_LINE_ENDING,
114+ auto_detect_line_ending, rope_slice_to_line_ending, LineEnding, DEFAULT_LINE_ENDING, get_line_ending
115115};
116116pub use transaction::{Assoc, Change, ChangeSet, Operation, Transaction};
helix-core/src/line_ending.rs+18−5
@@ -14,7 +14,7 @@ pub enum LineEnding {
1414}
1515
1616impl LineEnding {
17− pub fn len(&self) -> usize {
17+ pub fn len_chars(&self) -> usize {
1818 match self {
1919 Self::Crlf => 2,
2020 _ => 1,
@@ -28,10 +28,9 @@ impl LineEnding {
2828 Self::Nel => "\u{0085}",
2929 Self::LS => "\u{2028}",
3030 Self::CR => "\u{000D}",
31− _ => panic!(
32− "Unexpected line ending: {:?}, expected Crlf, LF, CR, Nel, or LS.",
33− self
34− ),
31+ Self::VT => "\u{000B}",
32+ Self::FF => "\u{000C}",
33+ Self::PS => "\u{2029}",
3534 }
3635 }
3736}
@@ -93,6 +92,20 @@ pub fn auto_detect_line_ending(doc: &Rope) -> Option<LineEnding> {
9392 ending
9493}
9594
95+/// Returns the passed line's line ending, if any.
96+pub fn get_line_ending(line: &RopeSlice) -> Option<LineEnding> {
97+ // Last character as str.
98+ let g1 = line.slice(line.len_chars().saturating_sub(1)..).as_str().unwrap();
99+
100+ // Last two characters as str, or empty str if they're not contiguous.
101+ // It's fine to punt on the non-contiguous case, because Ropey guarantees
102+ // that CRLF is always contiguous.
103+ let g2 = line.slice(line.len_chars().saturating_sub(2)..).as_str().unwrap_or("");
104+
105+ // First check the two-character case for CRLF, then check the single-character case.
106+ str_to_line_ending(g2).or_else(|| str_to_line_ending(g1))
107+}
108+
96109#[cfg(target_os = "windows")]
97110pub const DEFAULT_LINE_ENDING: LineEnding = LineEnding::Crlf;
98111#[cfg(not(target_os = "windows"))]
helix-term/src/commands.rs+5−7
@@ -5,7 +5,7 @@ use helix_core::{
55 object, pos_at_coords,
66 regex::{self, Regex},
77 register::{self, Register, Registers},
8− search, selection, Change, ChangeSet, LineEnding, Position, Range, Rope, RopeSlice, Selection,
8+ search, selection, Change, ChangeSet, LineEnding, Position, Range, Rope, RopeSlice, Selection, get_line_ending,
99 SmallVec, Tendril, Transaction,
1010};
1111
@@ -183,11 +183,10 @@ pub fn move_line_end(cx: &mut Context) {
183183 let text = doc.text();
184184 let line = text.char_to_line(range.head);
185185
186− // Line end is pos at the start of next line - 1
187− // subtract another 1 because the line ends with \n
188186 let pos = text
189187 .line_to_char(line + 1)
190− .saturating_sub(doc.line_ending().len() + 1);
188+ .saturating_sub(get_line_ending(&text.line(line)).map(|le| le.len_chars()).unwrap_or(0));
189+
191190 Range::new(pos, pos)
192191 });
193192
@@ -607,11 +606,10 @@ pub fn extend_line_end(cx: &mut Context) {
607606 let text = doc.text();
608607 let line = text.char_to_line(range.head);
609608
610− // Line end is pos at the start of next line - 1
611− // subtract another 1 because the line ends with \n
612609 let pos = text
613610 .line_to_char(line + 1)
614− .saturating_sub(doc.line_ending().len() + 1);
611+ .saturating_sub(get_line_ending(&text.line(line)).map(|le| le.len_chars()).unwrap_or(0));
612+
615613 Range::new(range.anchor, pos)
616614 });
617615