implemented most of selection backspace

This commit is contained in:
2025-12-09 19:25:40 -05:00
parent c4a1c89143
commit 5275161048
2 changed files with 108 additions and 55 deletions

View File

@@ -20,7 +20,9 @@
],
"folders": [
{
"path": "."
}
"path": ".",
"folder_exclude_patterns": ["*bin*"],
"binary_file_patterns": ["*.bin"]
},
]
}

View File

@@ -45,6 +45,11 @@ Selection :: struct {
end: Position,
}
Range :: struct {
start: int,
end: int,
}
window_width := 800
window_height := 600
font_size: f32 = 20.0
@@ -81,24 +86,34 @@ main :: proc() {
for c := r.GetCharPressed(); c != rune(0); c = r.GetCharPressed() {
chars, _ := utf8.encode_rune(c)
char := chars[0]
inject_at(&lines[cursor.line], cursor.char, char)
cursor.char += 1
// TODO: selection
if selection.active {
} else {
inject_at(&lines[cursor.line], cursor.char, char)
cursor.char += 1
}
}
move_cursor()
if repeatable_key_pressed(.ENTER) {
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)
// 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
}
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) {
@@ -114,30 +129,59 @@ main :: proc() {
skip_backspace: if repeatable_key_pressed(.BACKSPACE) {
if cursor.line == 0 && cursor.char == 0 do break skip_backspace
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
// 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)]))
defer delete(latest_line^)
ordered_remove(&lines, latest.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 i < cursor.line {
cursor.line -= 1
}
}
} else {
// delete single char
ordered_remove(&lines[cursor.line], cursor.char - 1)
cursor.char -= 1
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
}
}
}
}
@@ -257,24 +301,10 @@ render_line_with_selection :: proc(line: []u8, line_index: int, font: r.Font) {
earliest := selection_earliest()
latest := selection_latest()
selection_begin: int
selection_end: int
if line_index == earliest.line && line_index == latest.line {
selection_begin = min(selection.start.char, selection.end.char)
selection_end = max(selection.start.char, selection.end.char)
} else if line_index == earliest.line {
selection_begin = earliest.char
selection_end = len(line)
} else if line_index == latest.line {
selection_begin = 0
selection_end = latest.char
} else if earliest.line < line_index && line_index < latest.line {
selection_begin = 0
selection_end = len(line)
}
selection_range := get_selection_for_line(line, line_index)
prefix := line[:selection_begin]
suffix := line[selection_end:] if selection_end < len(line) else []u8{}
prefix := line[:selection_range.start]
suffix := line[selection_range.end:] if selection_range.end < len(line) else []u8{}
// need to copy these into separate buffers for zero value
x: f32 = 0.0
if len(prefix) != 0 {
@@ -286,10 +316,10 @@ render_line_with_selection :: proc(line: []u8, line_index: int, font: r.Font) {
}
selected_str: string
if selection_end < len(line) {
selected_str = string(line[selection_begin:selection_end])
if selection_range.end < len(line) {
selected_str = string(line[selection_range.start:selection_range.end])
} else {
selected_str = string(line[selection_begin:])
selected_str = string(line[selection_range.start:])
}
cstr :=
strings.clone_to_cstring(selected_str, context.temp_allocator) if len(suffix) != 0 else strings.unsafe_string_to_cstring(selected_str)
@@ -436,3 +466,24 @@ selection_latest :: proc() -> Position {
return latest
}
get_selection_for_line :: proc(line: []u8, line_index: int) -> Range {
earliest := selection_earliest()
latest := selection_latest()
selection_begin: int
selection_end: int
if line_index == earliest.line && line_index == latest.line {
selection_begin = min(selection.start.char, selection.end.char)
selection_end = max(selection.start.char, selection.end.char)
} else if line_index == earliest.line {
selection_begin = earliest.char
selection_end = len(line)
} else if line_index == latest.line {
selection_begin = 0
selection_end = latest.char
} else if earliest.line < line_index && line_index < latest.line {
selection_begin = 0
selection_end = len(line)
}
return Range{start = selection_begin, end = selection_end}
}