Skip to main content

typ_buffer/
line_ending.rs

1//! Which line terminator a file uses.
2//!
3//! Detected on load, recorded here, and written back by `save`. The rope holds
4//! LF only, so nothing between those two points has to know about `\r`.
5
6/// The line terminator a buffer was loaded with.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub enum LineEnding {
9    /// `\n`. The default for a new or newline-free file on every platform,
10    /// including Windows — a file TYPE creates has no existing convention to
11    /// honour, and LF is what the tools around it emit.
12    #[default]
13    Lf,
14    /// `\r\n`.
15    Crlf,
16}
17
18impl LineEnding {
19    /// What a status bar shows. The names every editor uses.
20    pub fn label(self) -> &'static str {
21        match self {
22            LineEnding::Lf => "LF",
23            LineEnding::Crlf => "CRLF",
24        }
25    }
26
27    /// The characters themselves, as `save` writes them.
28    pub fn as_str(self) -> &'static str {
29        match self {
30            LineEnding::Lf => "\n",
31            LineEnding::Crlf => "\r\n",
32        }
33    }
34
35    /// Detect from a file's contents.
36    ///
37    /// The **first** terminator decides. A mixed file is not a third kind of
38    /// file: whatever line one did is what the file is, and it is what gets
39    /// written back. Taking a majority instead would mean a save that silently
40    /// rewrites every line break in somebody's file because the count went the
41    /// other way.
42    ///
43    /// A lone `\r` is not a line ending. Classic Mac endings died with Mac OS 9
44    /// and a stray carriage return inside a line is far likelier, so treating
45    /// one as a terminator would misread an ordinary file badly.
46    pub fn detect(text: &str) -> Self {
47        match text.find('\n') {
48            Some(0) => LineEnding::Lf,
49            Some(index) if text.as_bytes()[index - 1] == b'\r' => LineEnding::Crlf,
50            Some(_) => LineEnding::Lf,
51            None => LineEnding::Lf,
52        }
53    }
54}