on master help sign in
Simplify some code.
cc058adBlaž Hrastnik
helix-core/src/lib.rs+1
@@ -53,6 +53,7 @@ pub use {regex, tree_sitter};
53
53
54pub use position::{coords_at_pos, pos_at_coords, Position};
54pub use position::{coords_at_pos, pos_at_coords, Position};
55pub use selection::{Range, Selection};
55pub use selection::{Range, Selection};
56+pub use smallvec::SmallVec;
56pub use syntax::Syntax;
57pub use syntax::Syntax;
57
58
58pub use diagnostic::Diagnostic;
59pub use diagnostic::Diagnostic;
helix-term/src/commands.rs+30−48
@@ -1,10 +1,10 @@
1use helix_core::{
1use helix_core::{
2− comment, coords_at_pos, graphemes, match_brackets,
2+ comment, coords_at_pos, graphemes, indent, match_brackets,
3 movement::{self, Direction},
3 movement::{self, Direction},
4 object, pos_at_coords,
4 object, pos_at_coords,
5 regex::{self, Regex},
5 regex::{self, Regex},
6 register, search, selection, Change, ChangeSet, Position, Range, Rope, RopeSlice, Selection,
6 register, search, selection, Change, ChangeSet, Position, Range, Rope, RopeSlice, Selection,
7− Tendril, Transaction,
7+ SmallVec, Tendril, Transaction,
8};
8};
9
9
10use once_cell::sync::Lazy;
10use once_cell::sync::Lazy;
@@ -951,26 +951,29 @@ pub fn open_below(cx: &mut Context) {
951 let (view, doc) = cx.current();
951 let (view, doc) = cx.current();
952 enter_insert_mode(doc);
952 enter_insert_mode(doc);
953
953
954+ let text = doc.text().slice(..);
954 let lines = selection_lines(doc.text(), doc.selection(view.id));
955 let lines = selection_lines(doc.text(), doc.selection(view.id));
955
956
956− let positions = lines.into_iter().map(|index| {
957+ let mut ranges = SmallVec::with_capacity(lines.len());
957− // adjust all positions to the end of the line (next line minus one)
958− doc.text().line_to_char(index + 1).saturating_sub(1)
959− });
960
958
961− let text = doc.text().slice(..);
959+ let changes: Vec<Change> = lines
960+ .into_iter()
961+ .map(|line| {
962+ // adjust all positions to the end of the line (next line minus one)
963+ let index = doc.text().line_to_char(line + 1).saturating_sub(1);
962
964
963− let changes: Vec<Change> = positions
964− .map(|index| {
965 // TODO: share logic with insert_newline for indentation
965 // TODO: share logic with insert_newline for indentation
966− let indent_level =
967− helix_core::indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
966+ let indent_level = indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
968 let indent = doc.indent_unit().repeat(indent_level);
967 let indent = doc.indent_unit().repeat(indent_level);
969 let mut text = String::with_capacity(1 + indent.len());
968 let mut text = String::with_capacity(1 + indent.len());
970 text.push('\n');
969 text.push('\n');
971 text.push_str(&indent);
970 text.push_str(&indent);
972 let text = text.repeat(count);
971 let text = text.repeat(count);
973
972
973+ // calculate new selection range
974+ let pos = index + text.len();
975+ ranges.push(Range::new(pos, pos));
976+
974 (index, index, Some(text.into()))
977 (index, index, Some(text.into()))
975 })
978 })
976 .collect();
979 .collect();
@@ -978,17 +981,7 @@ pub fn open_below(cx: &mut Context) {
978 // TODO: count actually inserts "n" new lines and starts editing on all of them.
981 // TODO: count actually inserts "n" new lines and starts editing on all of them.
979 // TODO: append "count" newlines and modify cursors to those lines
982 // TODO: append "count" newlines and modify cursors to those lines
980
983
981− let selection = Selection::new(
984+ let selection = Selection::new(ranges, 0);
982− changes
983− .iter()
984− .map(|(start, _end, text): &Change| {
985− let len = text.as_ref().map(|text| text.len()).unwrap(); // minus newline
986− let pos = start + len;
987− Range::new(pos, pos)
988− })
989− .collect(),
990− 0,
991− );
992
985
993 let transaction =
986 let transaction =
994 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
987 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
@@ -1002,26 +995,29 @@ pub fn open_above(cx: &mut Context) {
1002 let (view, doc) = cx.current();
995 let (view, doc) = cx.current();
1003 enter_insert_mode(doc);
996 enter_insert_mode(doc);
1004
997
998+ let text = doc.text().slice(..);
1005 let lines = selection_lines(doc.text(), doc.selection(view.id));
999 let lines = selection_lines(doc.text(), doc.selection(view.id));
1006
1000
1007− let positions = lines.into_iter().map(|index| {
1001+ let mut ranges = SmallVec::with_capacity(lines.len());
1008− // adjust all positions to the end of the previous line
1009− doc.text().line_to_char(index).saturating_sub(1)
1010− });
1011
1002
1012− let text = doc.text().slice(..);
1003+ let changes: Vec<Change> = lines
1004+ .into_iter()
1005+ .map(|line| {
1006+ // adjust all positions to the end of the previous line
1007+ let index = doc.text().line_to_char(line).saturating_sub(1);
1013
1008
1014− let changes: Vec<Change> = positions
1015− .map(|index| {
1016 // TODO: share logic with insert_newline for indentation
1009 // TODO: share logic with insert_newline for indentation
1017− let indent_level =
1018− helix_core::indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
1010+ let indent_level = indent::suggested_indent_for_pos(doc.syntax(), text, index, true);
1019 let indent = doc.indent_unit().repeat(indent_level);
1011 let indent = doc.indent_unit().repeat(indent_level);
1020 let mut text = String::with_capacity(1 + indent.len());
1012 let mut text = String::with_capacity(1 + indent.len());
1021 text.push('\n');
1013 text.push('\n');
1022 text.push_str(&indent);
1014 text.push_str(&indent);
1023 let text = text.repeat(count);
1015 let text = text.repeat(count);
1024
1016
1017+ // calculate new selection range
1018+ let pos = index + text.len();
1019+ ranges.push(Range::new(pos, pos));
1020+
1025 // generate changes
1021 // generate changes
1026 (index, index, Some(text.into()))
1022 (index, index, Some(text.into()))
1027 })
1023 })
@@ -1030,17 +1026,7 @@ pub fn open_above(cx: &mut Context) {
1030 // TODO: count actually inserts "n" new lines and starts editing on all of them.
1026 // TODO: count actually inserts "n" new lines and starts editing on all of them.
1031 // TODO: append "count" newlines and modify cursors to those lines
1027 // TODO: append "count" newlines and modify cursors to those lines
1032
1028
1033− let selection = Selection::new(
1029+ let selection = Selection::new(ranges, 0);
1034− changes
1035− .iter()
1036− .map(|(start, _end, text): &Change| {
1037− let len = text.as_ref().map(|text| text.len()).unwrap(); // minus newline
1038− let pos = start + len;
1039− Range::new(pos, pos)
1040− })
1041− .collect(),
1042− 0,
1043− );
1044
1030
1045 let transaction =
1031 let transaction =
1046 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
1032 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
@@ -1359,12 +1345,8 @@ pub mod insert {
1359 let transaction =
1345 let transaction =
1360 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
1346 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
1361 // TODO: offset range.head by 1? when calculating?
1347 // TODO: offset range.head by 1? when calculating?
1348+ let indent_level =
1362− let indent_level = helix_core::indent::suggested_indent_for_pos(
1349+ indent::suggested_indent_for_pos(doc.syntax(), text, range.head, true);
1363− doc.syntax(),
1364− text,
1365− range.head,
1366− true,
1367− );
1368 let indent = doc.indent_unit().repeat(indent_level);
1350 let indent = doc.indent_unit().repeat(indent_level);
1369 let mut text = String::with_capacity(1 + indent.len());
1351 let mut text = String::with_capacity(1 + indent.len());
1370 text.push('\n');
1352 text.push('\n');
helix-term/src/ui/mod.rs+9−4
@@ -82,7 +82,7 @@ pub fn file_picker(root: PathBuf) -> Picker<PathBuf> {
82 let files = Walk::new(root.clone()).filter_map(|entry| match entry {
82 let files = Walk::new(root.clone()).filter_map(|entry| match entry {
83 Ok(entry) => {
83 Ok(entry) => {
84 // filter dirs, but we might need special handling for symlinks!
84 // filter dirs, but we might need special handling for symlinks!
85− if !entry.file_type().unwrap().is_dir() {
85+ if !entry.file_type().map_or(false, |entry| entry.is_dir()) {
86 Some(entry.into_path())
86 Some(entry.into_path())
87 } else {
87 } else {
88 None
88 None
@@ -97,7 +97,11 @@ pub fn file_picker(root: PathBuf) -> Picker<PathBuf> {
97 files.take(MAX).collect(),
97 files.take(MAX).collect(),
98 move |path: &PathBuf| {
98 move |path: &PathBuf| {
99 // format_fn
99 // format_fn
100− path.strip_prefix(&root).unwrap().to_str().unwrap().into()
100+ path.strip_prefix(&root)
101+ .unwrap_or(path)
102+ .to_str()
103+ .unwrap()
104+ .into()
101 },
105 },
102 move |editor: &mut Editor, path: &PathBuf, action| {
106 move |editor: &mut Editor, path: &PathBuf, action| {
103 let document_id = editor
107 let document_id = editor
@@ -144,12 +148,13 @@ pub mod completers {
144 file.ok().map(|entry| {
148 file.ok().map(|entry| {
145 let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
149 let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
146
150
151+ let path = entry.path();
147− let mut path = entry.path().strip_prefix(&dir).unwrap().to_path_buf();
152+ let mut path = path.strip_prefix(&dir).unwrap_or(path).to_path_buf();
148
153
149 if is_dir {
154 if is_dir {
150 path.push("");
155 path.push("");
151 }
156 }
152− let path = path.to_str().unwrap().to_string();
157+ let path = path.to_str().unwrap().to_owned();
153 (end.clone(), Cow::from(path))
158 (end.clone(), Cow::from(path))
154 })
159 })
155 }) // TODO: unwrap or skip
160 }) // TODO: unwrap or skip