aboutsummaryrefslogtreecommitdiff
path: root/helix-view/src
diff options
context:
space:
mode:
Diffstat (limited to 'helix-view/src')
-rw-r--r--helix-view/src/document.rs34
-rw-r--r--helix-view/src/editor.rs41
-rw-r--r--helix-view/src/handlers/dap.rs2
3 files changed, 57 insertions, 20 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();
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index b9de57e1..c5a458d7 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -32,12 +32,12 @@ use anyhow::{bail, Error};
pub use helix_core::diagnostic::Severity;
pub use helix_core::register::Registers;
+use helix_core::Position;
use helix_core::{
auto_pairs::AutoPairs,
syntax::{self, AutoPairConfig},
Change,
};
-use helix_core::{Position, Selection};
use helix_dap as dap;
use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
@@ -590,6 +590,20 @@ impl Editor {
self.status_msg = Some((error.into(), Severity::Error));
}
+ #[inline]
+ pub fn get_status(&self) -> Option<(&Cow<'static, str>, &Severity)> {
+ self.status_msg.as_ref().map(|(status, sev)| (status, sev))
+ }
+
+ /// Returns true if the current status is an error
+ #[inline]
+ pub fn is_err(&self) -> bool {
+ self.status_msg
+ .as_ref()
+ .map(|(_, sev)| *sev == Severity::Error)
+ .unwrap_or(false)
+ }
+
pub fn set_theme(&mut self, theme: Theme) {
// `ui.selection` is the only scope required to be able to render a theme.
if theme.find_scope_index("ui.selection").is_none() {
@@ -664,11 +678,8 @@ impl Editor {
view.offset = Position::default();
let doc = self.documents.get_mut(&doc_id).unwrap();
+ doc.ensure_view_init(view.id);
- // initialize selection for view
- doc.selections
- .entry(view.id)
- .or_insert_with(|| Selection::point(0));
// TODO: reuse align_view
let pos = doc
.selection(view.id)
@@ -738,9 +749,7 @@ impl Editor {
Action::Load => {
let view_id = view!(self).id;
let doc = self.documents.get_mut(&id).unwrap();
- if doc.selections().is_empty() {
- doc.set_selection(view_id, Selection::point(0));
- }
+ doc.ensure_view_init(view_id);
return;
}
Action::HorizontalSplit | Action::VerticalSplit => {
@@ -755,7 +764,7 @@ impl Editor {
);
// initialize selection for view
let doc = self.documents.get_mut(&id).unwrap();
- doc.set_selection(view_id, Selection::point(0));
+ doc.ensure_view_init(view_id);
}
}
@@ -788,8 +797,9 @@ impl Editor {
Ok(self.new_file_from_document(action, Document::from(rope, Some(encoding))))
}
- pub fn open(&mut self, path: PathBuf, action: Action) -> Result<DocumentId, Error> {
- let path = helix_core::path::get_canonicalized_path(&path)?;
+ // ??? possible use for integration tests
+ pub fn open(&mut self, path: &Path, action: Action) -> Result<DocumentId, Error> {
+ let path = helix_core::path::get_canonicalized_path(path)?;
let id = self.document_by_path(&path).map(|doc| doc.id);
let id = if let Some(id) = id {
@@ -809,12 +819,7 @@ impl Editor {
pub fn close(&mut self, id: ViewId) {
let view = self.tree.get(self.tree.focus);
// remove selection
- self.documents
- .get_mut(&view.doc)
- .unwrap()
- .selections
- .remove(&id);
-
+ self.documents.get_mut(&view.doc).unwrap().remove_view(id);
self.tree.remove(id);
self._refresh();
}
@@ -889,7 +894,7 @@ impl Editor {
let view = View::new(doc_id, self.config().gutters.clone());
let view_id = self.tree.insert(view);
let doc = self.documents.get_mut(&doc_id).unwrap();
- doc.set_selection(view_id, Selection::point(0));
+ doc.ensure_view_init(view_id);
}
self._refresh();
diff --git a/helix-view/src/handlers/dap.rs b/helix-view/src/handlers/dap.rs
index b17ca353..ae1ae64c 100644
--- a/helix-view/src/handlers/dap.rs
+++ b/helix-view/src/handlers/dap.rs
@@ -62,7 +62,7 @@ pub fn jump_to_stack_frame(editor: &mut Editor, frame: &helix_dap::StackFrame) {
return;
};
- if let Err(e) = editor.open(path, Action::Replace) {
+ if let Err(e) = editor.open(&path, Action::Replace) {
editor.set_error(format!("Unable to jump to stack frame: {}", e));
return;
}