From b2b4ffe1bdc77baa810b60cf10e38c7b47c83eca Mon Sep 17 00:00:00 2001 From: Grant Horner Date: Tue, 9 Dec 2025 19:41:50 -0500 Subject: [PATCH] handle selection new line --- src/main.odin | 153 ++++++++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 73 deletions(-) diff --git a/src/main.odin b/src/main.odin index 53bf8c2..c40ccc5 100644 --- a/src/main.odin +++ b/src/main.odin @@ -96,24 +96,25 @@ main :: proc() { } move_cursor() + handle_backspace() if repeatable_key_pressed(.ENTER) { // TODO: selection if selection.active { - - } else { - new_line_cap := len(current_line()) - cursor.char - bs := make([dynamic]u8, 0, len(current_line()) == 0 ? 1 : new_line_cap * 2) - if cursor.char < len(current_line()) { - for c, i in current_line()[cursor.char:] { - append(&bs, c) - } - } - inject_at(&lines, cursor.line + 1, bs) - resize(current_line(), cursor.char) - cursor.line += 1 - cursor.char = 0 + delete_selection() + selection.active = false } + new_line_cap := len(current_line()) - cursor.char + bs := make([dynamic]u8, 0, len(current_line()) == 0 ? 1 : new_line_cap * 2) + if cursor.char < len(current_line()) { + for c, i in current_line()[cursor.char:] { + append(&bs, c) + } + } + inject_at(&lines, cursor.line + 1, bs) + resize(current_line(), cursor.char) + cursor.line += 1 + cursor.char = 0 } if r.IsKeyDown(.LEFT_SUPER) && r.IsKeyPressed(.S) { @@ -127,66 +128,6 @@ main :: proc() { fmt.println("Wrote file!") } - skip_backspace: if repeatable_key_pressed(.BACKSPACE) { - if cursor.line == 0 && cursor.char == 0 do break skip_backspace - // TODO: selection - if selection.active { - earliest := selection_earliest() - latest := selection_latest() - earliest_line := &lines[earliest.line] - earliest_selection := get_selection_for_line(earliest_line[:], earliest.line) - remove_range(earliest_line, earliest_selection.start, earliest_selection.end) - if latest.line != earliest.line { - latest_line := lines[latest.line] - latest_selection := get_selection_for_line(latest_line[:], latest.line) - append(earliest_line, string(latest_line[latest_selection.end:len(latest_line)])) - ordered_remove(&lines, latest.line) - delete(latest_line) - if selection.start.line < selection.end.line { - cursor.line -= 1 - } - for i := earliest.line + 1; i < latest.line; i += 1 { - line_to_remove := lines[i] - defer delete(line_to_remove) - ordered_remove(&lines, i) - // NOTE(grant): Should we do this here? - if selection.start.line < selection.end.line { - cursor.line -= 1 - } - } - } else { - cursor.char -= earliest_selection.end - earliest_selection.start - } - selection.active = false - } else { - if cursor.char == 0 { - // join lines - old_len := len(lines[cursor.line - 1]) - append(&lines[cursor.line - 1], string(current_line()[:])) - line_to_remove := current_line()^ - defer delete(line_to_remove) - ordered_remove(&lines, cursor.line) - cursor.line -= 1 - cursor.char = old_len - } else { - if r.IsKeyDown(.LEFT_ALT) { - // delete by word - delete_to, found := find_previous_space(cursor.char, current_line()[:]) - if found { - remove_range(current_line(), delete_to, cursor.char) - cursor.char = delete_to - } else { - remove_range(current_line(), 0, cursor.char) - cursor.char = 0 - } - } else { - // delete single char - ordered_remove(&lines[cursor.line], cursor.char - 1) - cursor.char -= 1 - } - } - } - } cursor_padding := 3 // move viewport up @@ -489,3 +430,69 @@ get_selection_for_line :: proc(line: []u8, line_index: int) -> Range { } return Range{start = selection_begin, end = selection_end} } + +handle_backspace :: proc() { + skip_backspace: if repeatable_key_pressed(.BACKSPACE) { + if cursor.line == 0 && cursor.char == 0 do break skip_backspace + // TODO: selection + if selection.active { + delete_selection() + selection.active = false + } else if cursor.char == 0 { + // join lines + old_len := len(lines[cursor.line - 1]) + append(&lines[cursor.line - 1], string(current_line()[:])) + line_to_remove := current_line()^ + defer delete(line_to_remove) + ordered_remove(&lines, cursor.line) + cursor.line -= 1 + cursor.char = old_len + } else if r.IsKeyDown(.LEFT_ALT) { + // delete by word + delete_to, found := find_previous_space(cursor.char, current_line()[:]) + if found { + remove_range(current_line(), delete_to, cursor.char) + cursor.char = delete_to + } else { + remove_range(current_line(), 0, cursor.char) + cursor.char = 0 + } + } else { + // delete single char + ordered_remove(&lines[cursor.line], cursor.char - 1) + cursor.char -= 1 + } + } +} + +delete_selection :: proc() { + earliest := selection_earliest() + latest := selection_latest() + earliest_line := &lines[earliest.line] + earliest_selection := get_selection_for_line(earliest_line[:], earliest.line) + remove_range(earliest_line, earliest_selection.start, earliest_selection.end) + if latest.line != earliest.line { + latest_line := lines[latest.line] + latest_selection := get_selection_for_line(latest_line[:], latest.line) + append(earliest_line, string(latest_line[latest_selection.end:len(latest_line)])) + ordered_remove(&lines, latest.line) + delete(latest_line) + if selection.start.line < selection.end.line { + cursor.line -= 1 + if selection.start.char < selection.end.char { + cursor.char -= selection.end.char - selection.start.char + } + } + for i := earliest.line + 1; i < latest.line; i += 1 { + line_to_remove := lines[i] + defer delete(line_to_remove) + ordered_remove(&lines, i) + // NOTE(grant): Should we do this here? + if selection.start.line < selection.end.line { + cursor.line -= 1 + } + } + } else { + cursor.char -= earliest_selection.end - earliest_selection.start + } +}