fix some memory isses
parent
0a0681c704
commit
cdadbbef18
|
@ -136,6 +136,8 @@ current_buffer :: proc(state: ^State) -> ^FileBuffer {
|
|||
}
|
||||
|
||||
yank_whole_line :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||
context.allocator = buffer.allocator
|
||||
|
||||
if state.yank_register.data != nil {
|
||||
delete(state.yank_register.data)
|
||||
state.yank_register.data = nil
|
||||
|
|
|
@ -825,8 +825,8 @@ color_character :: proc(buffer: ^FileBuffer, start: Cursor, end: Cursor, palette
|
|||
}
|
||||
|
||||
draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x, y, w, h: int, show_line_numbers: bool = true, show_cursor: bool = true) {
|
||||
glyph_width := math.min(256, int((w - state.source_font_width) / state.source_font_width));
|
||||
glyph_height := math.min(256, int((h - state.source_font_height*2) / state.source_font_height)) + 1;
|
||||
glyph_width := math.min(256, int(w / state.source_font_width));
|
||||
glyph_height := math.min(256, int(h / state.source_font_height)) + 1;
|
||||
|
||||
update_glyph_buffer(buffer, glyph_width, glyph_height);
|
||||
|
||||
|
@ -845,7 +845,7 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x, y, w, h: int, sh
|
|||
if show_cursor {
|
||||
if state.mode == .Normal {
|
||||
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Background4);
|
||||
} else if state.mode == .Visual {
|
||||
} else if state.mode == .Visual && buffer.selection != nil {
|
||||
start_sel_x := x + padding + buffer.selection.?.start.col * state.source_font_width;
|
||||
start_sel_y := y + buffer.selection.?.start.line * state.source_font_height;
|
||||
|
||||
|
@ -937,7 +937,9 @@ update_file_buffer_scroll :: proc(buffer: ^FileBuffer, cursor: Maybe(^Cursor) =
|
|||
cursor = &buffer.history.cursor;
|
||||
}
|
||||
|
||||
if cursor.?.line > (buffer.top_line + buffer.glyphs.height - 5) {
|
||||
if buffer.glyphs.height < 5 {
|
||||
buffer.top_line = cursor.?.line
|
||||
} else if cursor.?.line > (buffer.top_line + buffer.glyphs.height - 5) {
|
||||
buffer.top_line = math.max(cursor.?.line - buffer.glyphs.height + 5, 0);
|
||||
} else if cursor.?.line < (buffer.top_line + 5) {
|
||||
buffer.top_line = math.max(cursor.?.line - 5, 0);
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package core
|
||||
|
||||
import "core:log"
|
||||
import "core:mem"
|
||||
|
||||
FileHistory :: struct {
|
||||
allocator: mem.Allocator,
|
||||
|
||||
piece_table: PieceTable,
|
||||
cursor: Cursor,
|
||||
|
||||
|
@ -20,6 +23,7 @@ make_history_with_data :: proc(initial_data: []u8, starting_capacity: int = 1024
|
|||
context.allocator = allocator
|
||||
|
||||
return FileHistory {
|
||||
allocator = allocator,
|
||||
piece_table = make_piece_table(initial_data, starting_capacity = starting_capacity),
|
||||
snapshots = make([]Snapshot, starting_capacity),
|
||||
next = 0,
|
||||
|
@ -31,6 +35,7 @@ make_history_empty :: proc(starting_capacity: int = 1024, allocator := context.a
|
|||
context.allocator = allocator
|
||||
|
||||
return FileHistory {
|
||||
allocator = allocator,
|
||||
piece_table = make_piece_table(starting_capacity = starting_capacity),
|
||||
snapshots = make([]Snapshot, starting_capacity),
|
||||
next = 0,
|
||||
|
@ -54,6 +59,8 @@ free_history :: proc(history: ^FileHistory) {
|
|||
}
|
||||
|
||||
push_new_snapshot :: proc(history: ^FileHistory) {
|
||||
context.allocator = history.allocator
|
||||
|
||||
if history.snapshots[history.next].chunks != nil {
|
||||
delete(history.snapshots[history.next].chunks)
|
||||
}
|
||||
|
@ -65,6 +72,8 @@ push_new_snapshot :: proc(history: ^FileHistory) {
|
|||
}
|
||||
|
||||
pop_snapshot :: proc(history: ^FileHistory, make_new_snapshot: bool = false) {
|
||||
context.allocator = history.allocator
|
||||
|
||||
new_next, _ := next_indexes(history, backward = true)
|
||||
if new_next == history.next do return
|
||||
|
||||
|
@ -81,6 +90,8 @@ pop_snapshot :: proc(history: ^FileHistory, make_new_snapshot: bool = false) {
|
|||
}
|
||||
|
||||
recover_snapshot :: proc(history: ^FileHistory) {
|
||||
context.allocator = history.allocator
|
||||
|
||||
new_next, _ := next_indexes(history)
|
||||
if history.snapshots[new_next].chunks == nil do return
|
||||
history.next = new_next
|
||||
|
|
|
@ -84,9 +84,6 @@ render_file_buffer :: proc(state: ^core.State, s: ^ui.State, buffer: ^core.FileB
|
|||
draw_func := proc(state: ^core.State, e: ui.UI_Element, user_data: rawptr) {
|
||||
buffer := transmute(^core.FileBuffer)user_data;
|
||||
if buffer != nil {
|
||||
buffer.glyphs.width = e.layout.size.x / state.source_font_width;
|
||||
buffer.glyphs.height = e.layout.size.y / state.source_font_height + 1;
|
||||
|
||||
core.draw_file_buffer(state, buffer, e.layout.pos.x, e.layout.pos.y, e.layout.size.x, e.layout.size.y);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -58,7 +58,12 @@ make_grep_panel :: proc() -> core.Panel {
|
|||
|
||||
panel_state := &panel.type.(core.GrepPanel)
|
||||
|
||||
mem.arena_init(&panel_state.query_arena, make([]u8, 1024*1024*2))
|
||||
arena_bytes, err := make([]u8, 1024*1024*2)
|
||||
if err != nil {
|
||||
log.errorf("failed to allocate arena for grep panel: '%v'", err)
|
||||
return
|
||||
}
|
||||
mem.arena_init(&panel_state.query_arena, arena_bytes)
|
||||
|
||||
panel.input_map = core.new_input_map()
|
||||
panel_state.glyphs = core.make_glyph_buffer(256,256)
|
||||
|
@ -215,7 +220,7 @@ make_grep_panel :: proc() -> core.Panel {
|
|||
{
|
||||
defer ui.close_element(s)
|
||||
|
||||
// render_raw_buffer(state, s, &state.buffers[panel_state.buffer])
|
||||
render_raw_buffer(state, s, &panel_state.buffer)
|
||||
}
|
||||
}
|
||||
ui.close_element(s)
|
||||
|
@ -275,9 +280,6 @@ render_raw_buffer :: proc(state: ^core.State, s: ^ui.State, buffer: ^core.FileBu
|
|||
draw_func := proc(state: ^core.State, e: ui.UI_Element, user_data: rawptr) {
|
||||
buffer := transmute(^core.FileBuffer)user_data;
|
||||
if buffer != nil {
|
||||
buffer.glyphs.width = e.layout.size.x / state.source_font_width;
|
||||
buffer.glyphs.height = e.layout.size.y / state.source_font_height + 1;
|
||||
|
||||
core.draw_file_buffer(state, buffer, e.layout.pos.x, e.layout.pos.y, e.layout.size.x, e.layout.size.y, false);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -66,7 +66,14 @@ open :: proc(state: ^core.State, panel: core.Panel, make_active: bool = true) ->
|
|||
panel.id = panel_id
|
||||
state.current_panel = panel_id
|
||||
|
||||
mem.arena_init(&panel.arena, make([]u8, 1024*1024*4))
|
||||
arena_bytes, err := make([]u8, 1024*1024*8)
|
||||
if err != nil {
|
||||
log.errorf("failed to allocate memory for panel: '%v'", err)
|
||||
util.delete(&state.panels, panel_id)
|
||||
return
|
||||
}
|
||||
|
||||
mem.arena_init(&panel.arena, arena_bytes)
|
||||
panel.allocator = mem.arena_allocator(&panel.arena)
|
||||
|
||||
panel->create(state)
|
||||
|
|
|
@ -26,6 +26,10 @@ new_test_editor :: proc() -> core.State {
|
|||
return state
|
||||
}
|
||||
|
||||
delete_editor :: proc(e: ^core.State) {
|
||||
util.delete(&e.panels)
|
||||
}
|
||||
|
||||
buffer_to_string :: proc(buffer: ^core.FileBuffer) -> string {
|
||||
if buffer == nil {
|
||||
log.error("nil buffer")
|
||||
|
@ -84,9 +88,7 @@ input_text :: proc(text: string) -> ArtificialTextInput {
|
|||
}
|
||||
|
||||
setup_empty_buffer :: proc(state: ^core.State) {
|
||||
buffer := core.new_virtual_file_buffer(context.allocator);
|
||||
panels.open(state, panels.make_file_buffer_panel(len(state.buffers)))
|
||||
runtime.append(&state.buffers, buffer);
|
||||
panels.open(state, panels.make_file_buffer_panel(""))
|
||||
|
||||
core.reset_input_map(state)
|
||||
}
|
||||
|
@ -135,8 +137,12 @@ expect_cursor_index :: proc(t: ^testing.T, cursor: core.Cursor, chunk_index, cha
|
|||
insert_from_empty_no_newlines :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
inputted_text := "Hello, world!"
|
||||
expected_text := fmt.aprintf("%v\n", inputted_text)
|
||||
|
@ -146,6 +152,8 @@ insert_from_empty_no_newlines :: proc(t: ^testing.T) {
|
|||
expect_cursor_index(t, buffer.history.cursor, 0, 12)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
|
@ -153,8 +161,12 @@ insert_from_empty_no_newlines :: proc(t: ^testing.T) {
|
|||
insert_from_empty_with_newline :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
inputted_text := "Hello, world!\nThis is a new line"
|
||||
expected_text := fmt.aprintf("%v\n", inputted_text)
|
||||
|
@ -164,6 +176,8 @@ insert_from_empty_with_newline :: proc(t: ^testing.T) {
|
|||
expect_cursor_index(t, buffer.history.cursor, 0, 31)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
|
@ -171,8 +185,12 @@ insert_from_empty_with_newline :: proc(t: ^testing.T) {
|
|||
insert_in_between_text :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
inputted_text := "Hello, world!"
|
||||
expected_text := "Hello, beautiful world!\n"
|
||||
|
@ -188,6 +206,8 @@ insert_in_between_text :: proc(t: ^testing.T) {
|
|||
expect_cursor_index(t, buffer.history.cursor, 1, 9)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
|
@ -195,8 +215,12 @@ insert_in_between_text :: proc(t: ^testing.T) {
|
|||
insert_before_slice_at_beginning_of_file :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
inputted_text := "Hello, world!"
|
||||
expected_text := "Well, Hello, beautiful world!\n"
|
||||
|
@ -215,6 +239,8 @@ insert_before_slice_at_beginning_of_file :: proc(t: ^testing.T) {
|
|||
expect_cursor_index(t, buffer.history.cursor, 0, 5)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
|
@ -222,8 +248,12 @@ insert_before_slice_at_beginning_of_file :: proc(t: ^testing.T) {
|
|||
insert_before_slice :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
inputted_text := "Hello, world!"
|
||||
expected_text := "Hello, beautiful rich world!\n"
|
||||
|
@ -243,6 +273,8 @@ insert_before_slice :: proc(t: ^testing.T) {
|
|||
expect_cursor_index(t, buffer.history.cursor, 2, 4)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
|
@ -250,8 +282,12 @@ insert_before_slice :: proc(t: ^testing.T) {
|
|||
delete_last_content_slice_beginning_of_file :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "Hello, world!")
|
||||
|
||||
|
@ -283,8 +319,12 @@ delete_last_content_slice_beginning_of_file :: proc(t: ^testing.T) {
|
|||
delete_in_slice :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
inputted_text := "Hello, world!"
|
||||
expected_text := "Hello, beautiful h world!\n"
|
||||
|
@ -310,6 +350,8 @@ delete_in_slice :: proc(t: ^testing.T) {
|
|||
expect_cursor_index(t, buffer.history.cursor, 3, 0)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
|
@ -317,8 +359,12 @@ delete_in_slice :: proc(t: ^testing.T) {
|
|||
delete_across_slices :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
inputted_text := "Hello, world!"
|
||||
expected_text := "Hello, beautiful world!\n"
|
||||
|
@ -352,6 +398,8 @@ delete_across_slices :: proc(t: ^testing.T) {
|
|||
expect_cursor_index(t, buffer.history.cursor, 2, 0)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
|
@ -359,10 +407,14 @@ delete_across_slices :: proc(t: ^testing.T) {
|
|||
move_down_next_line_has_shorter_length :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
is_ctrl_pressed := false
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "012345678\n0")
|
||||
|
||||
|
@ -383,10 +435,14 @@ move_down_next_line_has_shorter_length :: proc(t: ^testing.T) {
|
|||
move_down_on_last_line :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
is_ctrl_pressed := false
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "012345678")
|
||||
|
||||
|
@ -402,8 +458,12 @@ move_down_on_last_line :: proc(t: ^testing.T) {
|
|||
move_left_at_beginning_of_file :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "01234")
|
||||
// Move cursor from --------^
|
||||
|
@ -425,10 +485,14 @@ move_left_at_beginning_of_file :: proc(t: ^testing.T) {
|
|||
move_right_at_end_of_file :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
is_ctrl_pressed := false
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "01234")
|
||||
|
||||
|
@ -447,10 +511,14 @@ move_right_at_end_of_file :: proc(t: ^testing.T) {
|
|||
move_to_end_of_line_from_end :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
is_ctrl_pressed := false
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "01234\n01234")
|
||||
|
||||
|
@ -468,10 +536,14 @@ move_to_end_of_line_from_end :: proc(t: ^testing.T) {
|
|||
move_to_end_of_line_from_middle :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
is_ctrl_pressed := false
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "01234\n01234")
|
||||
|
||||
|
@ -492,10 +564,14 @@ move_to_end_of_line_from_middle :: proc(t: ^testing.T) {
|
|||
move_to_beginning_of_line_from_middle :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
is_ctrl_pressed := false
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "01234\n01234")
|
||||
|
||||
|
@ -516,10 +592,14 @@ move_to_beginning_of_line_from_middle :: proc(t: ^testing.T) {
|
|||
move_to_beginning_of_line_from_start :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
is_ctrl_pressed := false
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "01234\n01234")
|
||||
|
||||
|
@ -540,8 +620,12 @@ move_to_beginning_of_line_from_start :: proc(t: ^testing.T) {
|
|||
append_end_of_line :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
run_text_insertion(&e, "hello")
|
||||
|
||||
|
@ -562,8 +646,12 @@ append_end_of_line :: proc(t: ^testing.T) {
|
|||
insert_line_under_current :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
initial_text := "Hello, world!\nThis is a new line"
|
||||
run_text_insertion(&e, initial_text)
|
||||
|
@ -590,6 +678,8 @@ insert_line_under_current :: proc(t: ^testing.T) {
|
|||
expect_cursor_index(t, buffer.history.cursor, 1, 23)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
|
@ -597,8 +687,12 @@ insert_line_under_current :: proc(t: ^testing.T) {
|
|||
yank_and_paste_whole_line :: proc(t: ^testing.T) {
|
||||
e := new_test_editor()
|
||||
setup_empty_buffer(&e)
|
||||
defer {
|
||||
panels.close(&e, 0)
|
||||
delete_editor(&e)
|
||||
}
|
||||
|
||||
buffer := &e.buffers[0]
|
||||
buffer := core.current_buffer(&e)
|
||||
|
||||
initial_text := "Hello, world!\nThis is a new line"
|
||||
run_text_insertion(&e, initial_text)
|
||||
|
@ -617,22 +711,22 @@ yank_and_paste_whole_line :: proc(t: ^testing.T) {
|
|||
expect_line_col(t, buffer.history.cursor, 1, 0)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
||||
testing.expectf(t, contents == expected_text, "got '%v', expected '%v'", contents, expected_text)
|
||||
}
|
||||
|
||||
run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pressed: ^bool) {
|
||||
log.infof("running input: %v", input)
|
||||
|
||||
{
|
||||
run_key_action := proc(state: ^core.State, control_key_pressed: bool, key: core.Key) -> bool {
|
||||
log.info("key_action")
|
||||
if current_panel, ok := state.current_panel.?; ok {
|
||||
panel := util.get(&state.panels, current_panel).?
|
||||
|
||||
if state.current_input_map != nil {
|
||||
if control_key_pressed {
|
||||
if action, exists := state.current_input_map.ctrl_key_actions[key]; exists {
|
||||
switch value in action.action {
|
||||
case core.EditorAction:
|
||||
value(state);
|
||||
value(state, panel);
|
||||
return true;
|
||||
case core.InputActions:
|
||||
state.current_input_map = &(&state.current_input_map.ctrl_key_actions[key]).action.(core.InputActions)
|
||||
|
@ -643,7 +737,7 @@ run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pre
|
|||
if action, exists := state.current_input_map.key_actions[key]; exists {
|
||||
switch value in action.action {
|
||||
case core.EditorAction:
|
||||
value(state);
|
||||
value(state, panel);
|
||||
return true;
|
||||
case core.InputActions:
|
||||
state.current_input_map = &(&state.current_input_map.key_actions[key]).action.(core.InputActions)
|
||||
|
@ -651,8 +745,6 @@ run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pre
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.info("current_input_map is null")
|
||||
}
|
||||
|
||||
return false
|
||||
|
@ -661,8 +753,6 @@ run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pre
|
|||
switch state.mode {
|
||||
case .Visual: fallthrough
|
||||
case .Normal: {
|
||||
log.info("it's normal/visual mode")
|
||||
|
||||
if key, ok := input.(ArtificialKey); ok {
|
||||
if key.is_down {
|
||||
if key.key == .LCTRL {
|
||||
|
@ -678,8 +768,6 @@ run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pre
|
|||
}
|
||||
}
|
||||
case .Insert: {
|
||||
log.info("it's insert mode")
|
||||
|
||||
buffer := core.current_buffer(state);
|
||||
|
||||
if key, ok := input.(ArtificialKey); ok {
|
||||
|
@ -710,24 +798,20 @@ run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pre
|
|||
}
|
||||
}
|
||||
|
||||
log.info("before text input")
|
||||
if text_input, ok := input.(ArtificialTextInput); ok {
|
||||
log.infof("attempting to append '%v' to buffer", text_input)
|
||||
|
||||
for char in text_input.text {
|
||||
if char < 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
if char == '\n' || (char >= 32 && char <= 125 && len(buffer.input_buffer) < 1024-1) {
|
||||
log.infof("appening '%v' to buffer", char)
|
||||
append(&buffer.input_buffer, u8(char));
|
||||
}
|
||||
}
|
||||
|
||||
if current_panel, ok := state.current_panel.?; ok {
|
||||
if panel, ok := util.get(&state.panels, current_panel).?; ok && panel.on_buffer_input_proc != nil {
|
||||
panel.on_buffer_input_proc(state, &panel.panel_state)
|
||||
if panel, ok := util.get(&state.panels, current_panel).?; ok && panel.on_buffer_input != nil {
|
||||
panel->on_buffer_input(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,6 +230,10 @@ delete_state :: proc(state: ^State) {
|
|||
}
|
||||
|
||||
parse_buffer :: proc(state: ^State, input: Input) {
|
||||
if state.parser == nil {
|
||||
return
|
||||
}
|
||||
|
||||
old_tree := state.tree
|
||||
if old_tree != nil {
|
||||
defer tree_delete(old_tree)
|
||||
|
|
|
@ -11,7 +11,7 @@ StaticListSlot :: struct($T: typeid) {
|
|||
data: T,
|
||||
}
|
||||
|
||||
append_static_list :: proc(list: ^StaticList($T), value: T) -> (id: int, panel: ^T, ok: bool) {
|
||||
append_static_list :: proc(list: ^StaticList($T), value: T) -> (id: int, item: ^T, ok: bool) {
|
||||
for i in 0..<len(list.data) {
|
||||
if !list.data[i].active {
|
||||
list.data[i].active = true
|
||||
|
@ -89,4 +89,8 @@ delete_static_list_elem :: proc(list: ^StaticList($T), index: int) {
|
|||
}
|
||||
}
|
||||
|
||||
delete :: proc{delete_static_list_elem}
|
||||
delete_static_list :: proc(list: ^StaticList($T)) {
|
||||
runtime.delete(list.data)
|
||||
}
|
||||
|
||||
delete :: proc{delete_static_list_elem, delete_static_list}
|
3
todo.md
3
todo.md
|
@ -1,5 +1,4 @@
|
|||
# Bugs
|
||||
- Memory Leak
|
||||
- Fix jumping forward a word jumping past consecutive brackets
|
||||
- Odd scrolling behavior on small screen heights
|
||||
- Scrolling past end/beginning of results panics
|
||||
|
@ -9,7 +8,7 @@
|
|||
|
||||
# Planned Features
|
||||
- [ ] Jump List
|
||||
- Use grouped lifetimes exclusively for memory allocation/freeing
|
||||
- [x] Use grouped lifetimes exclusively for memory allocation/freeing
|
||||
- [ ] Highlight which panel is currently active
|
||||
- [ ] Persist end of line cursor position
|
||||
- Testing Harness
|
||||
|
|
Loading…
Reference in New Issue