commands: Add goto first non-whitespace char of line

imgbot
Wojciech Kępka 3 years ago committed by Blaž Hrastnik
parent b873fb9897
commit 48df05b16d

@ -133,6 +133,7 @@ Jumps to various locations.
| e | Go to the end of the file | | e | Go to the end of the file |
| h | Go to the start of the line | | h | Go to the start of the line |
| l | Go to the end of the line | | l | Go to the end of the line |
| s | Go to first non-whitespace character of the line |
| t | Go to the top of the screen | | t | Go to the top of the screen |
| m | Go to the middle of the screen | | m | Go to the middle of the screen |
| b | Go to the bottom of the screen | | b | Go to the bottom of the screen |

@ -18,16 +18,8 @@ pub mod syntax;
mod transaction; mod transaction;
pub mod words; pub mod words;
pub(crate) fn find_first_non_whitespace_char2(line: RopeSlice) -> Option<usize> { pub fn find_first_non_whitespace_char2(line: RopeSlice) -> Option<usize> {
// find first non-whitespace char line.chars().position(|ch| !ch.is_whitespace())
for (start, ch) in line.chars().enumerate() {
// TODO: could use memchr with chunks?
if ch != ' ' && ch != '\t' && ch != '\n' {
return Some(start);
}
}
None
} }
pub(crate) fn find_first_non_whitespace_char(text: RopeSlice, line_num: usize) -> Option<usize> { pub(crate) fn find_first_non_whitespace_char(text: RopeSlice, line_num: usize) -> Option<usize> {
let line = text.line(line_num); let line = text.line(line_num);

@ -1,5 +1,6 @@
use helix_core::{ use helix_core::{
comment, coords_at_pos, find_root, graphemes, indent, match_brackets, comment, coords_at_pos, find_first_non_whitespace_char2, find_root, graphemes, indent,
match_brackets,
movement::{self, Direction}, movement::{self, Direction},
object, pos_at_coords, object, pos_at_coords,
regex::{self, Regex}, regex::{self, Regex},
@ -216,6 +217,24 @@ pub fn move_line_start(cx: &mut Context) {
doc.set_selection(view.id, selection); doc.set_selection(view.id, selection);
} }
pub fn move_first_nonwhitespace(cx: &mut Context) {
let (view, doc) = cx.current();
let selection = doc.selection(view.id).transform(|range| {
let text = doc.text();
let line_idx = text.char_to_line(range.head);
if let Some(pos) = find_first_non_whitespace_char2(text.line(line_idx)) {
let pos = pos + text.line_to_char(line_idx);
Range::new(pos, pos)
} else {
range
}
});
doc.set_selection(view.id, selection);
}
// TODO: move vs extend could take an extra type Extend/Move that would // TODO: move vs extend could take an extra type Extend/Move that would
// Range::new(if Move { pos } if Extend { range.anchor }, pos) // Range::new(if Move { pos } if Extend { range.anchor }, pos)
// since these all really do the same thing // since these all really do the same thing
@ -421,6 +440,24 @@ pub fn extend_prev_char(cx: &mut Context) {
) )
} }
pub fn extend_first_nonwhitespace(cx: &mut Context) {
let (view, doc) = cx.current();
let selection = doc.selection(view.id).transform(|range| {
let text = doc.text();
let line_idx = text.char_to_line(range.head);
if let Some(pos) = find_first_non_whitespace_char2(text.line(line_idx)) {
let pos = pos + text.line_to_char(line_idx);
Range::new(range.anchor, pos)
} else {
range
}
});
doc.set_selection(view.id, selection);
}
pub fn replace(cx: &mut Context) { pub fn replace(cx: &mut Context) {
// need to wait for next key // need to wait for next key
cx.on_next_key(move |cx, event| { cx.on_next_key(move |cx, event| {
@ -1288,6 +1325,8 @@ pub fn goto_mode(cx: &mut Context) {
(_, 'y') => goto_type_definition(cx), (_, 'y') => goto_type_definition(cx),
(_, 'r') => goto_reference(cx), (_, 'r') => goto_reference(cx),
(_, 'i') => goto_implementation(cx), (_, 'i') => goto_implementation(cx),
(Mode::Normal, 's') => move_first_nonwhitespace(cx),
(Mode::Select, 's') => extend_first_nonwhitespace(cx),
(_, 't') | (_, 'm') | (_, 'b') => { (_, 't') | (_, 'm') | (_, 'b') => {
let (view, doc) = cx.current(); let (view, doc) = cx.current();

Loading…
Cancel
Save