aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-core/src/lib.rs1
-rw-r--r--helix-term/src/commands.rs78
-rw-r--r--helix-term/src/ui/mod.rs13
3 files changed, 40 insertions, 52 deletions
diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs
index 30b3d37f..b3ce3c47 100644
--- a/helix-core/src/lib.rs
+++ b/helix-core/src/lib.rs
@@ -53,6 +53,7 @@ pub use {regex, tree_sitter};
pub use position::{coords_at_pos, pos_at_coords, Position};
pub use selection::{Range, Selection};
+pub use smallvec::SmallVec;
pub use syntax::Syntax;
pub use diagnostic::Diagnostic;
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 235cb52d..98ffa3d1 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -1,10 +1,10 @@
use helix_core::{
- comment, coords_at_pos, graphemes, match_brackets,
+ comment, coords_at_pos, graphemes, indent, match_brackets,
movement::{self, Direction},
object, pos_at_coords,
regex::{self, Regex},
register, search, selection, Change, ChangeSet, Position, Range, Rope, RopeSlice, Selection,
- Tendril, Transaction,
+ SmallVec, Tendril, Transaction,
};
use once_cell::sync::Lazy;
@@ -951,26 +951,29 @@ pub fn open_below(cx: &mut Context) {
let (view, doc) = cx.current();
enter_insert_mode(doc);
+ let text = doc.text().slice(..);
let lines = selection_lines(doc.text(), doc.selection(view.id));
- let positions = lines.into_iter().map(|index| {
- // adjust all positions to the end of the line (next line minus one)
- doc.text().line_to_char(index + 1).saturating_sub(1)
- });
+ let mut ranges = SmallVec::with_capacity(lines.len());
- let text = doc.text().slice(..);
+ let changes: Vec<Change> = lines
+ .into_iter()
+ .map(|line| {
+ // adjust all positions to the end of the line (next line minus one)
+ let index = doc.text().line_to_char(line + 1).saturating_sub(1);
- let changes: Vec<Change> = positions
- .map(|index| {
// TODO: share logic with insert_newline for indentation
- let indent_level =
- helix_core::indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
+ let indent_level = indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
let indent = doc.indent_unit().repeat(indent_level);
let mut text = String::with_capacity(1 + indent.len());
text.push('\n');
text.push_str(&indent);
let text = text.repeat(count);
+ // calculate new selection range
+ let pos = index + text.len();
+ ranges.push(Range::new(pos, pos));
+
(index, index, Some(text.into()))
})
.collect();
@@ -978,17 +981,7 @@ pub fn open_below(cx: &mut Context) {
// TODO: count actually inserts "n" new lines and starts editing on all of them.
// TODO: append "count" newlines and modify cursors to those lines
- let selection = Selection::new(
- changes
- .iter()
- .map(|(start, _end, text): &Change| {
- let len = text.as_ref().map(|text| text.len()).unwrap(); // minus newline
- let pos = start + len;
- Range::new(pos, pos)
- })
- .collect(),
- 0,
- );
+ let selection = Selection::new(ranges, 0);
let transaction =
Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
@@ -1002,26 +995,29 @@ pub fn open_above(cx: &mut Context) {
let (view, doc) = cx.current();
enter_insert_mode(doc);
+ let text = doc.text().slice(..);
let lines = selection_lines(doc.text(), doc.selection(view.id));
- let positions = lines.into_iter().map(|index| {
- // adjust all positions to the end of the previous line
- doc.text().line_to_char(index).saturating_sub(1)
- });
+ let mut ranges = SmallVec::with_capacity(lines.len());
- let text = doc.text().slice(..);
+ let changes: Vec<Change> = lines
+ .into_iter()
+ .map(|line| {
+ // adjust all positions to the end of the previous line
+ let index = doc.text().line_to_char(line).saturating_sub(1);
- let changes: Vec<Change> = positions
- .map(|index| {
// TODO: share logic with insert_newline for indentation
- let indent_level =
- helix_core::indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
+ let indent_level = indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
let indent = doc.indent_unit().repeat(indent_level);
let mut text = String::with_capacity(1 + indent.len());
text.push('\n');
text.push_str(&indent);
let text = text.repeat(count);
+ // calculate new selection range
+ let pos = index + text.len();
+ ranges.push(Range::new(pos, pos));
+
// generate changes
(index, index, Some(text.into()))
})
@@ -1030,17 +1026,7 @@ pub fn open_above(cx: &mut Context) {
// TODO: count actually inserts "n" new lines and starts editing on all of them.
// TODO: append "count" newlines and modify cursors to those lines
- let selection = Selection::new(
- changes
- .iter()
- .map(|(start, _end, text): &Change| {
- let len = text.as_ref().map(|text| text.len()).unwrap(); // minus newline
- let pos = start + len;
- Range::new(pos, pos)
- })
- .collect(),
- 0,
- );
+ let selection = Selection::new(ranges, 0);
let transaction =
Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
@@ -1359,12 +1345,8 @@ pub mod insert {
let transaction =
Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
// TODO: offset range.head by 1? when calculating?
- let indent_level = helix_core::indent::suggested_indent_for_pos(
- doc.syntax(),
- text,
- range.head,
- true,
- );
+ let indent_level =
+ indent::suggested_indent_for_pos(doc.syntax(), text, range.head, true);
let indent = doc.indent_unit().repeat(indent_level);
let mut text = String::with_capacity(1 + indent.len());
text.push('\n');
diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs
index 8cbf706e..57c08ddf 100644
--- a/helix-term/src/ui/mod.rs
+++ b/helix-term/src/ui/mod.rs
@@ -82,7 +82,7 @@ pub fn file_picker(root: PathBuf) -> Picker<PathBuf> {
let files = Walk::new(root.clone()).filter_map(|entry| match entry {
Ok(entry) => {
// filter dirs, but we might need special handling for symlinks!
- if !entry.file_type().unwrap().is_dir() {
+ if !entry.file_type().map_or(false, |entry| entry.is_dir()) {
Some(entry.into_path())
} else {
None
@@ -97,7 +97,11 @@ pub fn file_picker(root: PathBuf) -> Picker<PathBuf> {
files.take(MAX).collect(),
move |path: &PathBuf| {
// format_fn
- path.strip_prefix(&root).unwrap().to_str().unwrap().into()
+ path.strip_prefix(&root)
+ .unwrap_or(path)
+ .to_str()
+ .unwrap()
+ .into()
},
move |editor: &mut Editor, path: &PathBuf, action| {
let document_id = editor
@@ -144,12 +148,13 @@ pub mod completers {
file.ok().map(|entry| {
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
- let mut path = entry.path().strip_prefix(&dir).unwrap().to_path_buf();
+ let path = entry.path();
+ let mut path = path.strip_prefix(&dir).unwrap_or(path).to_path_buf();
if is_dir {
path.push("");
}
- let path = path.to_str().unwrap().to_string();
+ let path = path.to_str().unwrap().to_owned();
(end.clone(), Cow::from(path))
})
}) // TODO: unwrap or skip