commands: Add goto first non-whitespace char of line

This commit is contained in:
Wojciech Kępka 2021-06-08 08:25:55 +02:00 committed by Blaž Hrastnik
parent b873fb9897
commit 48df05b16d
3 changed files with 43 additions and 11 deletions

View File

@ -133,6 +133,7 @@ ## Goto mode
| e | Go to the end of the file |
| h | Go to the start 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 |
| m | Go to the middle of the screen |
| b | Go to the bottom of the screen |

View File

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

View File

@ -1,5 +1,6 @@
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},
object, pos_at_coords,
regex::{self, Regex},
@ -216,6 +217,24 @@ pub fn move_line_start(cx: &mut Context) {
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
// Range::new(if Move { pos } if Extend { range.anchor }, pos)
// 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) {
// need to wait for next key
cx.on_next_key(move |cx, event| {
@ -1288,6 +1325,8 @@ pub fn goto_mode(cx: &mut Context) {
(_, 'y') => goto_type_definition(cx),
(_, 'r') => goto_reference(cx),
(_, 'i') => goto_implementation(cx),
(Mode::Normal, 's') => move_first_nonwhitespace(cx),
(Mode::Select, 's') => extend_first_nonwhitespace(cx),
(_, 't') | (_, 'm') | (_, 'b') => {
let (view, doc) = cx.current();