aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-core/src/movement.rs5
-rw-r--r--helix-core/src/selection.rs2
-rw-r--r--helix-core/src/transaction.rs20
-rw-r--r--helix-term/src/commands.rs6
-rw-r--r--helix-term/src/ui/editor.rs2
-rw-r--r--helix-term/src/ui/prompt.rs2
-rw-r--r--helix-view/src/view.rs2
7 files changed, 31 insertions, 8 deletions
diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs
index 387b59b1..d6745fff 100644
--- a/helix-core/src/movement.rs
+++ b/helix-core/src/movement.rs
@@ -45,7 +45,10 @@ pub fn move_vertically(
let new_line = match dir {
Direction::Backward => row.saturating_sub(count),
- Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 2),
+ Direction::Forward => std::cmp::min(
+ row.saturating_add(count),
+ text.len_lines().saturating_sub(2),
+ ),
};
// convert to 0-indexed, subtract another 1 because len_chars() counts \n
diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs
index 67a20934..7dafc97a 100644
--- a/helix-core/src/selection.rs
+++ b/helix-core/src/selection.rs
@@ -383,7 +383,7 @@ pub fn split_on_matches(
// TODO: retain range direction
let end = text.byte_to_char(start_byte + mat.start());
- result.push(Range::new(start, end - 1));
+ result.push(Range::new(start, end.saturating_sub(1)));
start = text.byte_to_char(start_byte + mat.end());
}
diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs
index e61063f0..085f40b7 100644
--- a/helix-core/src/transaction.rs
+++ b/helix-core/src/transaction.rs
@@ -90,7 +90,8 @@ impl ChangeSet {
return;
}
- self.len_after += fragment.len();
+ // Avoiding std::str::len() to account for UTF-8 characters.
+ self.len_after += fragment.chars().count();
let new_last = match self.changes.as_mut_slice() {
[.., Insert(prev)] | [.., Insert(prev), Delete(_)] => {
@@ -754,4 +755,21 @@ mod test {
use Operation::*;
assert_eq!(changes.changes, &[Insert("a".into())]);
}
+
+ #[test]
+ fn combine_with_utf8() {
+ const TEST_CASE: &'static str = "Hello, これはヒレクスエディターです!";
+
+ let empty = Rope::from("");
+ let mut a = ChangeSet::new(&empty);
+
+ let mut b = ChangeSet::new(&empty);
+ b.insert(TEST_CASE.into());
+
+ let changes = a.compose(b);
+
+ use Operation::*;
+ assert_eq!(changes.changes, &[Insert(TEST_CASE.into())]);
+ assert_eq!(changes.len_after, TEST_CASE.chars().count());
+ }
}
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index bc11d0fe..12ec5e19 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -669,7 +669,7 @@ fn _search(doc: &mut Document, view: &mut View, contents: &str, regex: &Regex, e
return;
}
- let head = end - 1;
+ let head = end;
let selection = if extend {
selection.clone().push(Range::new(start, head))
@@ -749,7 +749,9 @@ pub fn select_line(cx: &mut Context) {
let line = text.char_to_line(pos.head);
let start = text.line_to_char(line);
- let end = text.line_to_char(line + count).saturating_sub(1);
+ let end = text
+ .line_to_char(std::cmp::min(doc.text().len_lines(), line + count))
+ .saturating_sub(1);
doc.set_selection(view.id, Selection::single(start, end));
}
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index f474cb36..6c39088e 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -341,7 +341,7 @@ impl EditorView {
let info: Style = theme.get("info");
let hint: Style = theme.get("hint");
- for (i, line) in (view.first_line..last_line).enumerate() {
+ for (i, line) in (view.first_line..=last_line).enumerate() {
use helix_core::diagnostic::Severity;
if let Some(diagnostic) = doc.diagnostics.iter().find(|d| d.line == line) {
surface.set_stringn(
diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs
index 1f424878..cdf303b8 100644
--- a/helix-term/src/ui/prompt.rs
+++ b/helix-term/src/ui/prompt.rs
@@ -114,7 +114,7 @@ impl Prompt {
let selected_color = theme.get("ui.menu.selected");
// completion
- let max_col = area.width / BASE_WIDTH;
+ let max_col = std::cmp::max(1, area.width / BASE_WIDTH);
let height = ((self.completion.len() as u16 + max_col - 1) / max_col);
let completion_area = Rect::new(
area.x,
diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs
index b7bfaa17..8eccb9ef 100644
--- a/helix-view/src/view.rs
+++ b/helix-view/src/view.rs
@@ -106,7 +106,7 @@ impl View {
/// Calculates the last visible line on screen
#[inline]
pub fn last_line(&self, doc: &Document) -> usize {
- let height = self.area.height.saturating_sub(1); // - 1 for statusline
+ let height = self.area.height.saturating_sub(2); // - 2 for statusline
std::cmp::min(
self.first_line + height as usize,
doc.text().len_lines() - 1,