mirror of https://github.com/helix-editor/helix
commands: Add goto first non-whitespace char of line
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…
Reference in New Issue