aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-core/src/comment.rs6
-rw-r--r--helix-core/src/history.rs13
-rw-r--r--helix-core/src/syntax.rs6
-rw-r--r--helix-core/src/transaction.rs48
-rw-r--r--helix-view/src/document.rs12
5 files changed, 48 insertions, 37 deletions
diff --git a/helix-core/src/comment.rs b/helix-core/src/comment.rs
index c3b91b4f..fd9d9058 100644
--- a/helix-core/src/comment.rs
+++ b/helix-core/src/comment.rs
@@ -96,13 +96,15 @@ mod test {
// comment
let transaction = toggle_line_comments(&state.doc, &state.selection);
- transaction.apply(&mut state);
+ transaction.apply(&mut state.doc);
+ state.selection = state.selection.clone().map(transaction.changes());
assert_eq!(state.doc, " // 1\n\n // 2\n // 3");
// uncomment
let transaction = toggle_line_comments(&state.doc, &state.selection);
- transaction.apply(&mut state);
+ transaction.apply(&mut state.doc);
+ state.selection = state.selection.clone().map(transaction.changes());
assert_eq!(state.doc, " 1\n\n 2\n 3");
// TODO: account for no margin after comment
diff --git a/helix-core/src/history.rs b/helix-core/src/history.rs
index 13a2a020..df4b9fc4 100644
--- a/helix-core/src/history.rs
+++ b/helix-core/src/history.rs
@@ -33,7 +33,10 @@ impl Default for History {
impl History {
pub fn commit_revision(&mut self, transaction: &Transaction, original: &State) {
// TODO: could store a single transaction, if deletes also stored the text they delete
- let revert = transaction.invert(original);
+ let revert = transaction
+ .invert(&original.doc)
+ // Store the current cursor position
+ .with_selection(original.selection.clone());
let new_cursor = self.revisions.len();
self.revisions.push(Revision {
@@ -100,7 +103,7 @@ mod test {
// Need to commit before applying!
history.commit_revision(&transaction1, &state);
- transaction1.apply(&mut state);
+ transaction1.apply(&mut state.doc);
assert_eq!("hello world!", state.doc);
// ---
@@ -110,18 +113,18 @@ mod test {
// Need to commit before applying!
history.commit_revision(&transaction2, &state);
- transaction2.apply(&mut state);
+ transaction2.apply(&mut state.doc);
assert_eq!("hello 世界!", state.doc);
// ---
fn undo(history: &mut History, state: &mut State) {
if let Some(transaction) = history.undo() {
- transaction.apply(state);
+ transaction.apply(&mut state.doc);
}
}
fn redo(history: &mut History, state: &mut State) {
if let Some(transaction) = history.redo() {
- transaction.apply(state);
+ transaction.apply(&mut state.doc);
}
}
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index b29d6165..6d6fe648 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -1593,7 +1593,7 @@ fn test_input_edits() {
&state.doc,
vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
);
- let edits = LanguageLayer::generate_edits(state.doc.slice(..), &transaction.changes);
+ let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
// transaction.apply(&mut state);
assert_eq!(
@@ -1622,8 +1622,8 @@ fn test_input_edits() {
let mut state = State::new("fn test() {}".into());
let transaction =
Transaction::change(&state.doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
- let edits = LanguageLayer::generate_edits(state.doc.slice(..), &transaction.changes);
- transaction.apply(&mut state);
+ let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
+ transaction.apply(&mut state.doc);
assert_eq!(state.doc, "fn test(a: u32) {}");
assert_eq!(
diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs
index c0f27abe..6c60c9c5 100644
--- a/helix-core/src/transaction.rs
+++ b/helix-core/src/transaction.rs
@@ -400,9 +400,7 @@ impl ChangeSet {
/// a single transaction.
#[derive(Debug, Clone)]
pub struct Transaction {
- /// Changes made to the buffer.
- pub(crate) changes: ChangeSet,
- /// When set, explicitly updates the selection.
+ changes: ChangeSet,
selection: Option<Selection>,
// effects, annotations
// scroll_into_view
@@ -417,40 +415,35 @@ impl Transaction {
}
}
+ /// Changes made to the buffer.
pub fn changes(&self) -> &ChangeSet {
&self.changes
}
+ /// When set, explicitly updates the selection.
+ pub fn selection(&self) -> Option<&Selection> {
+ self.selection.as_ref()
+ }
+
/// Returns true if applied successfully.
- pub fn apply(&self, state: &mut State) -> bool {
+ pub fn apply(&self, doc: &mut Rope) -> bool {
if !self.changes.is_empty() {
// apply changes to the document
- if !self.changes.apply(&mut state.doc) {
+ if !self.changes.apply(doc) {
return false;
}
}
- // TODO: also avoid mapping the selection if not necessary
-
- // update the selection: either take the selection specified in the transaction, or map the
- // current selection through changes.
- state.selection = self
- .selection
- .clone()
- .unwrap_or_else(|| state.selection.clone().map(&self.changes));
-
true
}
/// Generate a transaction that reverts this one.
- pub fn invert(&self, original: &State) -> Self {
- let changes = self.changes.invert(&original.doc);
- // Store the current cursor position
- let selection = original.selection.clone();
+ pub fn invert(&self, original: &Rope) -> Self {
+ let changes = self.changes.invert(original);
Self {
changes,
- selection: Some(selection),
+ selection: None,
}
}
@@ -675,7 +668,7 @@ mod test {
// (1, 1, None) is a useless 0-width delete
vec![(1, 1, None), (6, 11, Some("void".into())), (12, 17, None)].into_iter(),
);
- transaction.apply(&mut state);
+ transaction.apply(&mut state.doc);
assert_eq!(state.doc, Rope::from_str("hello void! 123"));
}
@@ -691,15 +684,20 @@ mod test {
fn optimized_composition() {
let mut state = State::new("".into());
let t1 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('h'));
- t1.apply(&mut state);
+ t1.apply(&mut state.doc);
+ state.selection = state.selection.clone().map(t1.changes());
let t2 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('e'));
- t2.apply(&mut state);
+ t2.apply(&mut state.doc);
+ state.selection = state.selection.clone().map(t2.changes());
let t3 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
- t3.apply(&mut state);
+ t3.apply(&mut state.doc);
+ state.selection = state.selection.clone().map(t3.changes());
let t4 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
- t4.apply(&mut state);
+ t4.apply(&mut state.doc);
+ state.selection = state.selection.clone().map(t4.changes());
let t5 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('o'));
- t5.apply(&mut state);
+ t5.apply(&mut state.doc);
+ state.selection = state.selection.clone().map(t5.changes());
assert_eq!(state.doc, Rope::from_str("hello"));
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index 94684362..cf160cca 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -21,6 +21,7 @@ pub struct Document {
// rope + selection
pub(crate) id: DocumentId,
state: State,
+
path: Option<PathBuf>,
/// Current editing mode.
@@ -185,9 +186,16 @@ impl Document {
fn _apply(&mut self, transaction: &Transaction) -> bool {
let old_doc = self.text().clone();
- let success = transaction.apply(&mut self.state);
+ let success = transaction.changes().apply(&mut self.state.doc);
if !transaction.changes().is_empty() {
+ // update the selection: either take the selection specified in the transaction, or map the
+ // current selection through changes.
+ self.state.selection = transaction
+ .selection()
+ .cloned()
+ .unwrap_or_else(|| self.selection().clone().map(transaction.changes()));
+
self.version += 1;
// update tree-sitter syntax tree
@@ -415,7 +423,7 @@ mod test {
// delete
- let transaction = transaction.invert(&old_doc);
+ let transaction = transaction.invert(&old_doc.doc);
let old_doc = doc.state.clone();
doc.apply(&transaction);
let changes = Client::changeset_to_changes(&old_doc.doc, doc.text(), transaction.changes());