on master help sign in
resolved conflict in rebase
5eb6918Jan Hrastnik
helix-core/src/lib.rs+2
@@ -6,6 +6,7 @@ pub mod diagnostic;
6pub mod graphemes;
6pub mod graphemes;
7pub mod history;
7pub mod history;
8pub mod indent;
8pub mod indent;
9+pub mod line_ending;
9pub mod macros;
10pub mod macros;
10pub mod match_brackets;
11pub mod match_brackets;
11pub mod movement;
12pub mod movement;
@@ -109,4 +110,5 @@ pub use syntax::Syntax;
109pub use diagnostic::Diagnostic;
110pub use diagnostic::Diagnostic;
110pub use state::State;
111pub use state::State;
111
112
113+pub use line_ending::{auto_detect_line_ending, default_line_ending, LineEnding};
112pub use transaction::{Assoc, Change, ChangeSet, Operation, Transaction};
114pub use transaction::{Assoc, Change, ChangeSet, Operation, Transaction};
helix-core/src/line_ending.rsnew file+74
@@ -0,0 +1,74 @@
1+use crate::{Rope, RopeGraphemes, RopeSlice};
2+
3+/// Represents one of the valid Unicode line endings.
4+#[derive(PartialEq, Copy, Clone, Debug)]
5+pub enum LineEnding {
6+ Crlf, // CarriageReturn followed by LineFeed
7+ LF, // U+000A -- LineFeed
8+ VT, // U+000B -- VerticalTab
9+ FF, // U+000C -- FormFeed
10+ CR, // U+000D -- CarriageReturn
11+ Nel, // U+0085 -- NextLine
12+ LS, // U+2028 -- Line Separator
13+ PS, // U+2029 -- ParagraphSeparator
14+}
15+
16+pub fn rope_slice_to_line_ending(g: &RopeSlice) -> Option<LineEnding> {
17+ if let Some(text) = g.as_str() {
18+ str_to_line_ending(text)
19+ } else if g == "\u{000D}\u{000A}" {
20+ Some(LineEnding::Crlf)
21+ } else {
22+ // Not a line ending
23+ None
24+ }
25+}
26+
27+pub fn str_to_line_ending(g: &str) -> Option<LineEnding> {
28+ match g {
29+ "\u{000D}\u{000A}" => Some(LineEnding::Crlf),
30+ "\u{000A}" => Some(LineEnding::LF),
31+ "\u{000B}" => Some(LineEnding::VT),
32+ "\u{000C}" => Some(LineEnding::FF),
33+ "\u{000D}" => Some(LineEnding::CR),
34+ "\u{0085}" => Some(LineEnding::Nel),
35+ "\u{2028}" => Some(LineEnding::LS),
36+ "\u{2029}" => Some(LineEnding::PS),
37+
38+ // Not a line ending
39+ _ => None,
40+ }
41+}
42+
43+pub fn auto_detect_line_ending(doc: &Rope) -> Option<LineEnding> {
44+ // based on https://github.com/cessen/led/blob/27572c8838a1c664ee378a19358604063881cc1d/src/editor/mod.rs#L88-L162
45+
46+ let mut ending = None;
47+ for line in doc.lines().take(1) {
48+ // check first line only - unsure how sound this is
49+ ending = match line.len_chars() {
50+ 1 => {
51+ let g = RopeGraphemes::new(line.slice((line.len_chars() - 1)..))
52+ .last()
53+ .unwrap();
54+ rope_slice_to_line_ending(&g)
55+ }
56+ n if n > 1 => {
57+ let g = RopeGraphemes::new(line.slice((line.len_chars() - 2)..))
58+ .last()
59+ .unwrap();
60+ rope_slice_to_line_ending(&g)
61+ }
62+ _ => None,
63+ }
64+ }
65+ ending
66+}
67+
68+pub fn default_line_ending() -> Option<LineEnding> {
69+ if cfg!(windows) {
70+ Some(LineEnding::Crlf)
71+ } else {
72+ Some(LineEnding::LF)
73+ }
74+}
helix-view/src/document.rs+21−54
@@ -5,11 +5,14 @@ use std::path::{Component, Path, PathBuf};
5use std::sync::Arc;
5use std::sync::Arc;
6
6
7use helix_core::{
7use helix_core::{
8+<<<<<<< HEAD
8 chars::{char_is_linebreak, char_is_whitespace},
9 chars::{char_is_linebreak, char_is_whitespace},
9 history::History,
10 history::History,
11+=======
12+ auto_detect_line_ending, default_line_ending,
13+>>>>>>> 491a8b3 (resolved conflict in rebase)
10 syntax::{LanguageConfiguration, LOADER},
14 syntax::{LanguageConfiguration, LOADER},
11− ChangeSet, Diagnostic, History, Rope, RopeGraphemes, RopeSlice, Selection, State, Syntax,
15+ ChangeSet, Diagnostic, History, LineEnding, Rope, Selection, State, Syntax, Transaction,
12− Transaction,
13};
16};
14
17
15use crate::{DocumentId, ViewId};
18use crate::{DocumentId, ViewId};
@@ -23,6 +26,7 @@ pub enum Mode {
23 Insert,
26 Insert,
24}
27}
25
28
29+<<<<<<< HEAD
26
30
27#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
31#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
28pub enum IndentStyle {
32pub enum IndentStyle {
@@ -45,6 +49,8 @@ pub enum LineEnding {
45 PS = 8, // U+2029 -- ParagraphSeparator
49 PS = 8, // U+2029 -- ParagraphSeparator
46}
50}
47
51
52+=======
53+>>>>>>> 491a8b3 (resolved conflict in rebase)
48pub struct Document {
54pub struct Document {
49 // rope + selection
55 // rope + selection
50 pub(crate) id: DocumentId,
56 pub(crate) id: DocumentId,
@@ -78,7 +84,7 @@ pub struct Document {
78
84
79 diagnostics: Vec<Diagnostic>,
85 diagnostics: Vec<Diagnostic>,
80 language_server: Option<Arc<helix_lsp::Client>>,
86 language_server: Option<Arc<helix_lsp::Client>>,
81− _line_ending: LineEnding,
87+ line_ending: Option<LineEnding>,
82}
88}
83
89
84use std::fmt;
90use std::fmt;
@@ -164,61 +170,14 @@ pub fn canonicalize_path(path: &Path) -> std::io::Result<PathBuf> {
164 std::env::current_dir().map(|current_dir| normalize_path(&current_dir.join(path)))
170 std::env::current_dir().map(|current_dir| normalize_path(&current_dir.join(path)))
165}
171}
166
172
167−pub fn auto_detect_line_ending(doc: &Rope) -> LineEnding {
168− // based on https://github.com/cessen/led/blob/27572c8838a1c664ee378a19358604063881cc1d/src/editor/mod.rs#L88-L162
169−
170− let mut ending = LineEnding::None;
171− for line in doc.lines().take(1) { // check first line only - unsure how sound this is
172− ending = match line.len_chars() {
173− 1 => { let g = RopeGraphemes::new(line.slice((line.len_chars() - 1)..))
174− .last()
175− .unwrap();
176− rope_slice_to_line_ending(&g)}
177− n if n > 1 => { let g = RopeGraphemes::new(line.slice((line.len_chars() - 2)..))
178− .last()
179− .unwrap();
180− rope_slice_to_line_ending(&g) }
181− _ => LineEnding::None
182−
183− }
184− }
185− ending
186−}
187−
188−pub fn rope_slice_to_line_ending(g: &RopeSlice) -> LineEnding {
189− if let Some(text) = g.as_str() {
190− str_to_line_ending(text)
191− } else if g == "\u{000D}\u{000A}" {
192− LineEnding::Crlf
193− } else {
194− // Not a line ending
195− LineEnding::None
196− }
197−}
198−
199−pub fn str_to_line_ending(g: &str) -> LineEnding {
200− match g {
201− "\u{000D}\u{000A}" => LineEnding::Crlf,
202− "\u{000A}" => LineEnding::LF,
203− "\u{000B}" => LineEnding::VT,
204− "\u{000C}" => LineEnding::FF,
205− "\u{000D}" => LineEnding::CR,
206− "\u{0085}" => LineEnding::Nel,
207− "\u{2028}" => LineEnding::LS,
208− "\u{2029}" => LineEnding::PS,
209−
210− // Not a line ending
211− _ => LineEnding::None,
212− }
213−}
214−
215use helix_lsp::lsp;
173use helix_lsp::lsp;
216use url::Url;
174use url::Url;
217
175
218impl Document {
176impl Document {
219− pub fn new(text: Rope, _line_ending: LineEnding) -> Self {
177+ pub fn new(text: Rope) -> Self {
220 let changes = ChangeSet::new(&text);
178 let changes = ChangeSet::new(&text);
221 let old_state = None;
179 let old_state = None;
180+ let line_ending = default_line_ending();
222
181
223 Self {
182 Self {
224 id: DocumentId::default(),
183 id: DocumentId::default(),
@@ -237,7 +196,7 @@ impl Document {
237 history: Cell::new(History::default()),
196 history: Cell::new(History::default()),
238 last_saved_revision: 0,
197 last_saved_revision: 0,
239 language_server: None,
198 language_server: None,
240− _line_ending
199+ line_ending,
241 }
200 }
242 }
201 }
243
202
@@ -260,10 +219,14 @@ impl Document {
260 // search for line endings
219 // search for line endings
261 let line_ending = auto_detect_line_ending(&doc);
220 let line_ending = auto_detect_line_ending(&doc);
262
221
263− let mut doc = Self::new(doc, line_ending);
222+ let mut doc = Self::new(doc);
264 // set the path and try detecting the language
223 // set the path and try detecting the language
265 doc.set_path(&path)?;
224 doc.set_path(&path)?;
225+<<<<<<< HEAD
266 doc.detect_indent_style();
226 doc.detect_indent_style();
227+=======
228+ doc.set_line_ending(line_ending);
229+>>>>>>> 491a8b3 (resolved conflict in rebase)
267
230
268 Ok(doc)
231 Ok(doc)
269 }
232 }
@@ -522,6 +485,10 @@ impl Document {
522 self.selections.insert(view_id, selection);
485 self.selections.insert(view_id, selection);
523 }
486 }
524
487
488+ pub fn set_line_ending(&mut self, line_ending: Option<LineEnding>) {
489+ self.line_ending = line_ending;
490+ }
491+
525 fn _apply(&mut self, transaction: &Transaction, view_id: ViewId) -> bool {
492 fn _apply(&mut self, transaction: &Transaction, view_id: ViewId) -> bool {
526 let old_doc = self.text().clone();
493 let old_doc = self.text().clone();
527
494
helix-view/src/editor.rs+6−4
@@ -1,6 +1,4 @@
1−use crate::{
2− theme::Theme, tree::Tree, Document, DocumentId, LineEnding, RegisterSelection, View, ViewId,
1+use crate::{theme::Theme, tree::Tree, Document, DocumentId, RegisterSelection, View, ViewId};
3−};
4use tui::layout::Rect;
2use tui::layout::Rect;
5use tui::terminal::CursorKind;
3use tui::terminal::CursorKind;
6
4
@@ -10,9 +8,13 @@ use slotmap::SlotMap;
10
8
11use anyhow::Error;
9use anyhow::Error;
12
10
11+<<<<<<< HEAD
13pub use helix_core::diagnostic::Severity;
12pub use helix_core::diagnostic::Severity;
14pub use helix_core::register::Registers;
13pub use helix_core::register::Registers;
15use helix_core::Position;
14use helix_core::Position;
15+=======
16+pub use helix_core::{diagnostic::Severity, LineEnding};
17+>>>>>>> 491a8b3 (resolved conflict in rebase)
16
18
17#[derive(Debug)]
19#[derive(Debug)]
18pub struct Editor {
20pub struct Editor {
@@ -150,7 +152,7 @@ impl Editor {
150
152
151 pub fn new_file(&mut self, action: Action) -> DocumentId {
153 pub fn new_file(&mut self, action: Action) -> DocumentId {
152 use helix_core::Rope;
154 use helix_core::Rope;
153− let doc = Document::new(Rope::from("\n"), LineEnding::LF);
155+ let doc = Document::new(Rope::from("\n"));
154 let id = self.documents.insert(doc);
156 let id = self.documents.insert(doc);
155 self.documents[id].id = id;
157 self.documents[id].id = id;
156 self.switch(id, action);
158 self.switch(id, action);
helix-view/src/lib.rs−1
@@ -10,7 +10,6 @@ new_key_type! { pub struct DocumentId; }
10new_key_type! { pub struct ViewId; }
10new_key_type! { pub struct ViewId; }
11
11
12pub use document::Document;
12pub use document::Document;
13−pub use document::LineEnding;
14pub use editor::Editor;
13pub use editor::Editor;
15pub use register_selection::RegisterSelection;
14pub use register_selection::RegisterSelection;
16pub use theme::Theme;
15pub use theme::Theme;