@@ -365,6 +365,7 @@ impl MappableCommand {
365 extend_to_line_end, "Extend to line end",
365 extend_to_line_end, "Extend to line end",
366 extend_to_line_end_newline, "Extend to line end",
366 extend_to_line_end_newline, "Extend to line end",
367 signature_help, "Show signature help",
367 signature_help, "Show signature help",
368+ smart_tab, "Insert tab if all cursors have all whitespace to their left; otherwise, run a separate command.",
368 insert_tab, "Insert tab char",
369 insert_tab, "Insert tab char",
369 insert_newline, "Insert newline char",
370 insert_newline, "Insert newline char",
370 delete_char_backward, "Delete previous char",
371 delete_char_backward, "Delete previous char",
@@ -2521,6 +2522,10 @@ fn insert_mode(cx: &mut Context) {
2521 .transform(|range| Range::new(range.to(), range.from()));
2522 .transform(|range| Range::new(range.to(), range.from()));
2523 doc.set_selection(view.id, selection);
2524 doc.set_selection(view.id, selection);
2526+ // [TODO] temporary workaround until we're not using the idle timer to
2527+ // trigger auto completions any more
2528+ cx.editor.clear_idle_timer();
2526// inserts at the end of each selection
2531// inserts at the end of each selection
@@ -3444,6 +3449,7 @@ pub mod insert {
3446 use helix_core::auto_pairs;
3451 use helix_core::auto_pairs;
3452+ use helix_view::editor::SmartTabConfig;
3448 pub fn insert_char(cx: &mut Context, c: char) {
3454 pub fn insert_char(cx: &mut Context, c: char) {
3449 let (view, doc) = current_ref!(cx.editor);
3455 let (view, doc) = current_ref!(cx.editor);
@@ -3469,6 +3475,31 @@ pub mod insert {
3478+ pub fn smart_tab(cx: &mut Context) {
3479+ let (view, doc) = current_ref!(cx.editor);
3480+ let view_id = view.id;
3483+ cx.editor.config().smart_tab,
3484+ Some(SmartTabConfig { enable: true, .. })
3486+ let cursors_after_whitespace = doc.selection(view_id).ranges().iter().all(|range| {
3487+ let cursor = range.cursor(doc.text().slice(..));
3488+ let current_line_num = doc.text().char_to_line(cursor);
3489+ let current_line_start = doc.text().line_to_char(current_line_num);
3490+ let left = doc.text().slice(current_line_start..cursor);
3491+ left.chars().all(|c| c.is_whitespace())
3494+ if !cursors_after_whitespace {
3495+ move_parent_node_end(cx);
3472 pub fn insert_tab(cx: &mut Context) {
3503 pub fn insert_tab(cx: &mut Context) {
3473 let (view, doc) = current!(cx.editor);
3504 let (view, doc) = current!(cx.editor);
3474 // TODO: round out to nearest indentation level (for example a line with 3 spaces should
3505 // TODO: round out to nearest indentation level (for example a line with 3 spaces should
@@ -4626,11 +4657,14 @@ fn move_node_bound_impl(cx: &mut Context, dir: Direction, movement: Movement) {
4628 doc.set_selection(view.id, selection);
4659 doc.set_selection(view.id, selection);
4661+ // [TODO] temporary workaround until we're not using the idle timer to
4662+ // trigger auto completions any more
4663+ editor.clear_idle_timer();
4633− cx.editor.last_motion = Some(Motion(Box::new(motion)));
4667+ cx.editor.apply_motion(motion);
4636pub fn move_parent_node_end(cx: &mut Context) {
4670pub fn move_parent_node_end(cx: &mut Context) {