Skip to content

Commit

Permalink
WIP: auto indent on insert_at_line_start
Browse files Browse the repository at this point in the history
  • Loading branch information
CptPotato committed Feb 5, 2023
1 parent b2e83f8 commit 6f45df3
Showing 1 changed file with 80 additions and 2 deletions.
82 changes: 80 additions & 2 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use helix_core::{
history::UndoKind,
increment, indent,
indent::IndentStyle,
line_ending::{get_line_ending_of_str, line_end_char_index, str_is_line_ending},
line_ending::{
get_line_ending_of_str, line_end_char_index, line_without_line_ending, str_is_line_ending,
},
match_brackets,
movement::{self, move_vertically_visual, Direction},
object, pos_at_coords,
Expand Down Expand Up @@ -2659,9 +2661,85 @@ fn last_picker(cx: &mut Context) {
}

// I inserts at the first nonwhitespace character of each line with a selection
// If the line is empty, automatically indent
fn insert_at_line_start(cx: &mut Context) {
goto_first_nonwhitespace(cx);
enter_insert_mode(cx);

let (view, doc) = current!(cx.editor);

let text = doc.text().slice(..);
let contents = doc.text();
let selection = doc.selection(view.id);

let language_config = doc.language_config();
let syntax = doc.syntax();
let tab_width = doc.tab_width();

let mut ranges = SmallVec::with_capacity(selection.len());
let mut offs = 0;

let mut transaction = Transaction::change_by_selection(contents, selection, |range| {
let cursor = range.from();
let cursor_line = text.char_to_line(cursor);

let doc_end = contents.len_chars();
if range.from() == doc_end {
ranges.push(Range::point(doc_end + offs));
return (doc_end, doc_end, None);
}

let line_content = line_without_line_ending(&text, cursor_line);
if line_content.len_chars() == 0 {
// line is empty => auto indent
let (line_end_index, line_end_offset_width) = if cursor_line == 0 {
(0, 0)
} else {
(
line_end_char_index(&doc.text().slice(..), cursor_line),
doc.line_ending.len_chars(),
)
};

let indent = indent::indent_for_newline(
language_config,
syntax,
&doc.indent_style,
tab_width,
text,
cursor_line,
line_end_index,
cursor_line,
);

let indent_len = indent.len();
let mut text = String::with_capacity(indent_len);
text.push_str(&indent);

// calculate new selection ranges
let pos = offs + line_end_index + line_end_offset_width;
ranges.push(Range::point((pos + indent_len).saturating_sub(1)));

offs += text.chars().count();
(line_end_index, line_end_index, Some(text.into()))
} else {
// move cursor to the first non-whitespace character of the current line
let first_non_ws = line_content
.chars()
.enumerate()
.find_map(|(i, c)| if !c.is_whitespace() { Some(i) } else { None })
.unwrap_or_default();

let pos = offs + text.line_to_char(cursor_line) + first_non_ws;
ranges.push(Range::point(pos));
(pos, pos, None)
}
});

transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index()));
doc.apply(&transaction, view.id);

// goto_first_nonwhitespace(cx);
// enter_insert_mode(cx);
}

// A inserts at the end of each line with a selection
Expand Down

0 comments on commit 6f45df3

Please sign in to comment.