aboutsummaryrefslogtreecommitdiff
path: root/helix-view/src/document.rs
diff options
context:
space:
mode:
authorSkyler Hawthorne2022-03-17 03:34:21 +0000
committerSkyler Hawthorne2022-06-19 03:54:03 +0000
commit0f3c10a021bbe79e20bde1f55b87465edeec476d (patch)
treea2d54e96885b5761e806eddd9bd8206071d15e8c /helix-view/src/document.rs
parent502d3290fb88d8a871b0824adc7987a98104933d (diff)
Fix initial selection of Document in new view
When a new View of a Document is created, a default cursor of 0, 0 is created, and it does not get normalized to a single width cursor until at least one movement of the cursor happens. This appears to have no practical negative effect that I could find, but it makes tests difficult to work with, since the initial selection is not what you expect it to be. This changes the initial selection of a new View to be the width of the first grapheme in the text.
Diffstat (limited to 'helix-view/src/document.rs')
-rw-r--r--helix-view/src/document.rs34
1 files changed, 33 insertions, 1 deletions
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index a2d2af77..00adaa1a 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -1,5 +1,6 @@
use anyhow::{anyhow, bail, Context, Error};
use helix_core::auto_pairs::AutoPairs;
+use helix_core::Range;
use serde::de::{self, Deserialize, Deserializer};
use serde::Serialize;
use std::cell::Cell;
@@ -83,7 +84,7 @@ impl Serialize for Mode {
pub struct Document {
pub(crate) id: DocumentId,
text: Rope,
- pub(crate) selections: HashMap<ViewId, Selection>,
+ selections: HashMap<ViewId, Selection>,
path: Option<PathBuf>,
encoding: &'static encoding::Encoding,
@@ -637,6 +638,37 @@ impl Document {
.insert(view_id, selection.ensure_invariants(self.text().slice(..)));
}
+ /// Find the origin selection of the text in a document, i.e. where
+ /// a single cursor would go if it were on the first grapheme. If
+ /// the text is empty, returns (0, 0).
+ pub fn origin(&self) -> Range {
+ if self.text().len_chars() == 0 {
+ return Range::new(0, 0);
+ }
+
+ Range::new(0, 1).grapheme_aligned(self.text().slice(..))
+ }
+
+ /// Reset the view's selection on this document to the
+ /// [origin](Document::origin) cursor.
+ pub fn reset_selection(&mut self, view_id: ViewId) {
+ let origin = self.origin();
+ self.set_selection(view_id, Selection::single(origin.anchor, origin.head));
+ }
+
+ /// Initializes a new selection for the given view if it does not
+ /// already have one.
+ pub fn ensure_view_init(&mut self, view_id: ViewId) {
+ if self.selections.get(&view_id).is_none() {
+ self.reset_selection(view_id);
+ }
+ }
+
+ /// Remove a view's selection from this document.
+ pub fn remove_view(&mut self, view_id: ViewId) {
+ self.selections.remove(&view_id);
+ }
+
/// Apply a [`Transaction`] to the [`Document`] to change its text.
fn apply_impl(&mut self, transaction: &Transaction, view_id: ViewId) -> bool {
let old_doc = self.text().clone();