on master help sign in
Fully drop State references.
9eaef6eBlaž Hrastnik
helix-core/src/comment.rs+4−2
@@ -96,13 +96,15 @@ mod test {
96
96
97 // comment
97 // comment
98 let transaction = toggle_line_comments(&state.doc, &state.selection);
98 let transaction = toggle_line_comments(&state.doc, &state.selection);
99− transaction.apply(&mut state);
99+ transaction.apply(&mut state.doc);
100+ state.selection = state.selection.clone().map(transaction.changes());
100
101
101 assert_eq!(state.doc, " // 1\n\n // 2\n // 3");
102 assert_eq!(state.doc, " // 1\n\n // 2\n // 3");
102
103
103 // uncomment
104 // uncomment
104 let transaction = toggle_line_comments(&state.doc, &state.selection);
105 let transaction = toggle_line_comments(&state.doc, &state.selection);
105− transaction.apply(&mut state);
106+ transaction.apply(&mut state.doc);
107+ state.selection = state.selection.clone().map(transaction.changes());
106 assert_eq!(state.doc, " 1\n\n 2\n 3");
108 assert_eq!(state.doc, " 1\n\n 2\n 3");
107
109
108 // TODO: account for no margin after comment
110 // TODO: account for no margin after comment
helix-core/src/history.rs+8−5
@@ -33,7 +33,10 @@ impl Default for History {
33impl History {
33impl History {
34 pub fn commit_revision(&mut self, transaction: &Transaction, original: &State) {
34 pub fn commit_revision(&mut self, transaction: &Transaction, original: &State) {
35 // TODO: could store a single transaction, if deletes also stored the text they delete
35 // TODO: could store a single transaction, if deletes also stored the text they delete
36− let revert = transaction.invert(original);
36+ let revert = transaction
37+ .invert(&original.doc)
38+ // Store the current cursor position
39+ .with_selection(original.selection.clone());
37
40
38 let new_cursor = self.revisions.len();
41 let new_cursor = self.revisions.len();
39 self.revisions.push(Revision {
42 self.revisions.push(Revision {
@@ -100,7 +103,7 @@ mod test {
100
103
101 // Need to commit before applying!
104 // Need to commit before applying!
102 history.commit_revision(&transaction1, &state);
105 history.commit_revision(&transaction1, &state);
103− transaction1.apply(&mut state);
106+ transaction1.apply(&mut state.doc);
104 assert_eq!("hello world!", state.doc);
107 assert_eq!("hello world!", state.doc);
105
108
106 // ---
109 // ---
@@ -110,18 +113,18 @@ mod test {
110
113
111 // Need to commit before applying!
114 // Need to commit before applying!
112 history.commit_revision(&transaction2, &state);
115 history.commit_revision(&transaction2, &state);
113− transaction2.apply(&mut state);
116+ transaction2.apply(&mut state.doc);
114 assert_eq!("hello 世界!", state.doc);
117 assert_eq!("hello 世界!", state.doc);
115
118
116 // ---
119 // ---
117 fn undo(history: &mut History, state: &mut State) {
120 fn undo(history: &mut History, state: &mut State) {
118 if let Some(transaction) = history.undo() {
121 if let Some(transaction) = history.undo() {
119− transaction.apply(state);
122+ transaction.apply(&mut state.doc);
120 }
123 }
121 }
124 }
122 fn redo(history: &mut History, state: &mut State) {
125 fn redo(history: &mut History, state: &mut State) {
123 if let Some(transaction) = history.redo() {
126 if let Some(transaction) = history.redo() {
124− transaction.apply(state);
127+ transaction.apply(&mut state.doc);
125 }
128 }
126 }
129 }
127
130
helix-core/src/syntax.rs+3−3
@@ -1593,7 +1593,7 @@ fn test_input_edits() {
1593 &state.doc,
1593 &state.doc,
1594 vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
1594 vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
1595 );
1595 );
1596− let edits = LanguageLayer::generate_edits(state.doc.slice(..), &transaction.changes);
1596+ let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
1597 // transaction.apply(&mut state);
1597 // transaction.apply(&mut state);
1598
1598
1599 assert_eq!(
1599 assert_eq!(
@@ -1622,8 +1622,8 @@ fn test_input_edits() {
1622 let mut state = State::new("fn test() {}".into());
1622 let mut state = State::new("fn test() {}".into());
1623 let transaction =
1623 let transaction =
1624 Transaction::change(&state.doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
1624 Transaction::change(&state.doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
1625− let edits = LanguageLayer::generate_edits(state.doc.slice(..), &transaction.changes);
1625+ let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
1626− transaction.apply(&mut state);
1626+ transaction.apply(&mut state.doc);
1627
1627
1628 assert_eq!(state.doc, "fn test(a: u32) {}");
1628 assert_eq!(state.doc, "fn test(a: u32) {}");
1629 assert_eq!(
1629 assert_eq!(
helix-core/src/transaction.rs+23−25
@@ -400,9 +400,7 @@ impl ChangeSet {
400/// a single transaction.
400/// a single transaction.
401#[derive(Debug, Clone)]
401#[derive(Debug, Clone)]
402pub struct Transaction {
402pub struct Transaction {
403− /// Changes made to the buffer.
404− pub(crate) changes: ChangeSet,
403+ changes: ChangeSet,
405− /// When set, explicitly updates the selection.
406 selection: Option<Selection>,
404 selection: Option<Selection>,
407 // effects, annotations
405 // effects, annotations
408 // scroll_into_view
406 // scroll_into_view
@@ -417,40 +415,35 @@ impl Transaction {
417 }
415 }
418 }
416 }
419
417
418+ /// Changes made to the buffer.
420 pub fn changes(&self) -> &ChangeSet {
419 pub fn changes(&self) -> &ChangeSet {
421 &self.changes
420 &self.changes
422 }
421 }
423
422
423+ /// When set, explicitly updates the selection.
424+ pub fn selection(&self) -> Option<&Selection> {
425+ self.selection.as_ref()
426+ }
427+
424 /// Returns true if applied successfully.
428 /// Returns true if applied successfully.
425− pub fn apply(&self, state: &mut State) -> bool {
429+ pub fn apply(&self, doc: &mut Rope) -> bool {
426 if !self.changes.is_empty() {
430 if !self.changes.is_empty() {
427 // apply changes to the document
431 // apply changes to the document
428− if !self.changes.apply(&mut state.doc) {
432+ if !self.changes.apply(doc) {
429 return false;
433 return false;
430 }
434 }
431 }
435 }
432
436
433− // TODO: also avoid mapping the selection if not necessary
434−
435− // update the selection: either take the selection specified in the transaction, or map the
436− // current selection through changes.
437− state.selection = self
438− .selection
439− .clone()
440− .unwrap_or_else(|| state.selection.clone().map(&self.changes));
441−
442 true
437 true
443 }
438 }
444
439
445 /// Generate a transaction that reverts this one.
440 /// Generate a transaction that reverts this one.
446− pub fn invert(&self, original: &State) -> Self {
441+ pub fn invert(&self, original: &Rope) -> Self {
447− let changes = self.changes.invert(&original.doc);
442+ let changes = self.changes.invert(original);
448− // Store the current cursor position
449− let selection = original.selection.clone();
450
443
451 Self {
444 Self {
452 changes,
445 changes,
453− selection: Some(selection),
446+ selection: None,
454 }
447 }
455 }
448 }
456
449
@@ -675,7 +668,7 @@ mod test {
675 // (1, 1, None) is a useless 0-width delete
668 // (1, 1, None) is a useless 0-width delete
676 vec![(1, 1, None), (6, 11, Some("void".into())), (12, 17, None)].into_iter(),
669 vec![(1, 1, None), (6, 11, Some("void".into())), (12, 17, None)].into_iter(),
677 );
670 );
678− transaction.apply(&mut state);
671+ transaction.apply(&mut state.doc);
679 assert_eq!(state.doc, Rope::from_str("hello void! 123"));
672 assert_eq!(state.doc, Rope::from_str("hello void! 123"));
680 }
673 }
681
674
@@ -691,15 +684,20 @@ mod test {
691 fn optimized_composition() {
684 fn optimized_composition() {
692 let mut state = State::new("".into());
685 let mut state = State::new("".into());
693 let t1 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('h'));
686 let t1 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('h'));
694− t1.apply(&mut state);
687+ t1.apply(&mut state.doc);
688+ state.selection = state.selection.clone().map(t1.changes());
695 let t2 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('e'));
689 let t2 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('e'));
696− t2.apply(&mut state);
690+ t2.apply(&mut state.doc);
691+ state.selection = state.selection.clone().map(t2.changes());
697 let t3 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
692 let t3 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
698− t3.apply(&mut state);
693+ t3.apply(&mut state.doc);
694+ state.selection = state.selection.clone().map(t3.changes());
699 let t4 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
695 let t4 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
700− t4.apply(&mut state);
696+ t4.apply(&mut state.doc);
697+ state.selection = state.selection.clone().map(t4.changes());
701 let t5 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('o'));
698 let t5 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('o'));
702− t5.apply(&mut state);
699+ t5.apply(&mut state.doc);
700+ state.selection = state.selection.clone().map(t5.changes());
703
701
704 assert_eq!(state.doc, Rope::from_str("hello"));
702 assert_eq!(state.doc, Rope::from_str("hello"));
705
703
helix-view/src/document.rs+10−2
@@ -21,6 +21,7 @@ pub struct Document {
21 // rope + selection
21 // rope + selection
22 pub(crate) id: DocumentId,
22 pub(crate) id: DocumentId,
23 state: State,
23 state: State,
24+
24 path: Option<PathBuf>,
25 path: Option<PathBuf>,
25
26
26 /// Current editing mode.
27 /// Current editing mode.
@@ -185,9 +186,16 @@ impl Document {
185 fn _apply(&mut self, transaction: &Transaction) -> bool {
186 fn _apply(&mut self, transaction: &Transaction) -> bool {
186 let old_doc = self.text().clone();
187 let old_doc = self.text().clone();
187
188
188− let success = transaction.apply(&mut self.state);
189+ let success = transaction.changes().apply(&mut self.state.doc);
189
190
190 if !transaction.changes().is_empty() {
191 if !transaction.changes().is_empty() {
192+ // update the selection: either take the selection specified in the transaction, or map the
193+ // current selection through changes.
194+ self.state.selection = transaction
195+ .selection()
196+ .cloned()
197+ .unwrap_or_else(|| self.selection().clone().map(transaction.changes()));
198+
191 self.version += 1;
199 self.version += 1;
192
200
193 // update tree-sitter syntax tree
201 // update tree-sitter syntax tree
@@ -415,7 +423,7 @@ mod test {
415
423
416 // delete
424 // delete
417
425
418− let transaction = transaction.invert(&old_doc);
426+ let transaction = transaction.invert(&old_doc.doc);
419 let old_doc = doc.state.clone();
427 let old_doc = doc.state.clone();
420 doc.apply(&transaction);
428 doc.apply(&transaction);
421 let changes = Client::changeset_to_changes(&old_doc.doc, doc.text(), transaction.changes());
429 let changes = Client::changeset_to_changes(&old_doc.doc, doc.text(), transaction.changes());