diff --git a/src/core/core.odin b/src/core/core.odin index e3001da..e304de6 100644 --- a/src/core/core.odin +++ b/src/core/core.odin @@ -51,6 +51,7 @@ State :: struct { current_panel: Maybe(int), panels: util.StaticList(Panel), + buffers: util.StaticList(FileBuffer), } Register :: struct { @@ -100,7 +101,7 @@ PanelType :: union { } FileBufferPanel :: struct { - buffer: FileBuffer, + buffer_id: int, viewed_symbol: Maybe(string), search_buffer: FileBuffer, @@ -143,6 +144,26 @@ current_buffer :: proc(state: ^State) -> ^FileBuffer { return nil } +new_buffer_virtual :: proc(state: ^State) -> (id: int, buffer: ^FileBuffer, ok: bool) { + return util.append(&state.buffers, new_virtual_file_buffer(context.allocator)) +} + +new_buffer_file :: proc(state: ^State, file_path: string) -> (id: int, buffer: ^FileBuffer, ok: bool) { + new_buffer, err := new_file_buffer(context.allocator, file_path, state.directory) + if err.type != .None { + ok = false + return + } + + return util.append(&state.buffers, new_buffer) +} + +new_buffer :: proc{new_buffer_file, new_buffer_virtual} + +get_buffer :: proc(state: ^State, buffer_id: int) -> Maybe(^FileBuffer) { + return util.get(&state.buffers, buffer_id) +} + yank_whole_line :: proc(state: ^State, buffer: ^FileBuffer) { if state.yank_register.data != nil { delete(state.yank_register.data) diff --git a/src/main.odin b/src/main.odin index a7cffb3..f345e13 100644 --- a/src/main.odin +++ b/src/main.odin @@ -160,6 +160,7 @@ main :: proc() { command_arena = mem.arena_allocator(&_command_arena), panels = util.make_static_list(core.Panel, 128), + buffers = util.make_static_list(core.FileBuffer, 64), directory = os.get_current_directory(), log_buffer = core.new_virtual_file_buffer(context.allocator), diff --git a/src/panels/file_buffer.odin b/src/panels/file_buffer.odin index e8f1a62..eff259b 100644 --- a/src/panels/file_buffer.odin +++ b/src/panels/file_buffer.odin @@ -41,9 +41,6 @@ make_file_buffer_panel :: proc(file_path: string, line: int = 0, col: int = 0) - col = col, }, drop = proc(panel: ^core.Panel, state: ^core.State) { - panel_state := &panel.type.(core.FileBufferPanel) - - ts.delete_state(&panel_state.buffer.tree) }, create = proc(panel: ^core.Panel, state: ^core.State) { context.allocator = panel.allocator @@ -61,20 +58,22 @@ make_file_buffer_panel :: proc(file_path: string, line: int = 0, col: int = 0) - panel_state.search_buffer = core.new_virtual_file_buffer(panel.allocator) if len(panel_state.file_path) == 0 { - panel_state.buffer = core.new_virtual_file_buffer(panel.allocator) - } else { - buffer, err := core.new_file_buffer(panel.allocator, panel_state.file_path, state.directory) - if err.type != .None { - log.error("Failed to create file buffer:", err); - return; + if buffer_id, _, ok := core.new_buffer(state); ok { + panel_state.buffer_id = buffer_id + } else { + log.error("failed to create buffer") } + } else { + if buffer_id, buffer, ok := core.new_buffer(state, panel_state.file_path); ok { + buffer.history.cursor.line = panel_state.line + buffer.history.cursor.col = panel_state.col + buffer.top_line = buffer.history.cursor.line + core.update_file_buffer_index_from_cursor(buffer) - buffer.history.cursor.line = panel_state.line - buffer.history.cursor.col = panel_state.col - buffer.top_line = buffer.history.cursor.line - core.update_file_buffer_index_from_cursor(&buffer) - - panel_state.buffer = buffer + panel_state.buffer_id = buffer_id + } else { + log.error("failed to create buffer") + } } leader_actions := core.new_input_actions(show_help = true) @@ -96,26 +95,29 @@ make_file_buffer_panel :: proc(file_path: string, line: int = 0, col: int = 0) - if panel_state.is_searching { return &panel_state.search_buffer, true } else { - return &panel_state.buffer, true + buffer, ok = core.get_buffer(state, panel_state.buffer_id).? + return } }, on_buffer_input = proc(panel: ^core.Panel, state: ^core.State) { panel_state := &panel.type.(core.FileBufferPanel) - run_query(panel_state, &panel_state.buffer) + buffer := core.get_buffer(state, panel_state.buffer_id).? + + run_query(panel_state, buffer) if panel_state.is_searching { if len(panel_state.query_results) > 0 { for result, i in panel_state.query_results { - cursor := panel_state.buffer.history.cursor + cursor := buffer.history.cursor if result.line >= cursor.line || (result.line == cursor.line && result.col >= cursor.col) { - core.move_cursor_to_location(&panel_state.buffer, result.line, result.col) + core.move_cursor_to_location(buffer, result.line, result.col) break } if i == len(panel_state.query_results)-1 { result := panel_state.query_results[0] - core.move_cursor_to_location(&panel_state.buffer, result.line, result.col) + core.move_cursor_to_location(buffer, result.line, result.col) } } } @@ -123,6 +125,7 @@ make_file_buffer_panel :: proc(file_path: string, line: int = 0, col: int = 0) - }, render = proc(panel: ^core.Panel, state: ^core.State) -> (ok: bool) { panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? s := transmute(^ui.State)state.ui @@ -133,7 +136,7 @@ make_file_buffer_panel :: proc(file_path: string, line: int = 0, col: int = 0) - }, ) { - render_file_buffer(state, s, &panel_state.buffer) + render_file_buffer(state, s, buffer) if panel_state.is_searching { ui.open_element(s, nil, { @@ -248,7 +251,7 @@ file_buffer_leader_actions :: proc(input_map: ^core.InputActions) { core.register_key_action(input_map, .K, proc(state: ^core.State, user_data: rawptr) { panel := transmute(^core.Panel)user_data panel_state := &panel.type.(core.FileBufferPanel) - buffer := &panel_state.buffer + buffer := core.get_buffer(state, panel_state.buffer_id).? ts.update_cursor(&buffer.tree, buffer.history.cursor.line, buffer.history.cursor.col) panel_state.viewed_symbol = ts.print_node_type(&buffer.tree) @@ -259,13 +262,17 @@ file_buffer_leader_actions :: proc(input_map: ^core.InputActions) { file_buffer_go_actions :: proc(input_map: ^core.InputActions) { core.register_key_action(input_map, .H, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_start_of_line(buffer); core.reset_input_map(state) }, "move to beginning of line"); core.register_key_action(input_map, .L, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_end_of_line(buffer); core.reset_input_map(state) @@ -274,7 +281,9 @@ file_buffer_go_actions :: proc(input_map: ^core.InputActions) { file_buffer_delete_actions :: proc(input_map: ^core.InputActions) { core.register_key_action(input_map, .D, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.push_new_snapshot(&buffer.history) @@ -295,50 +304,68 @@ file_buffer_input_actions :: proc(input_map: ^core.InputActions) { // Cursor Movement { core.register_key_action(input_map, .W, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_forward_start_of_word(buffer); }, "move forward one word"); core.register_key_action(input_map, .E, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_forward_end_of_word(buffer); }, "move forward to end of word"); core.register_key_action(input_map, .B, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_backward_start_of_word(buffer); }, "move backward one word"); core.register_key_action(input_map, .K, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_up(buffer); }, "move up one line"); core.register_key_action(input_map, .J, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_down(buffer); }, "move down one line"); core.register_key_action(input_map, .H, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_left(buffer); }, "move left one char"); core.register_key_action(input_map, .L, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.move_cursor_right(buffer); }, "move right one char"); core.register_ctrl_key_action(input_map, .U, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.scroll_file_buffer(buffer, .Up); }, "scroll buffer up"); core.register_ctrl_key_action(input_map, .D, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.scroll_file_buffer(buffer, .Down); }, "scroll buffer up"); @@ -365,7 +392,9 @@ file_buffer_input_actions :: proc(input_map: ^core.InputActions) { // Save file core.register_ctrl_key_action(input_map, .S, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? if err := core.save_buffer_to_disk(state, buffer); err != nil { log.errorf("failed to save buffer to disk: %v", err) @@ -395,7 +424,9 @@ file_buffer_input_actions :: proc(input_map: ^core.InputActions) { }, "search buffer") core.register_key_action(input_map, .V, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? state.mode = .Visual; core.reset_input_map(state) @@ -418,19 +449,20 @@ file_buffer_input_actions :: proc(input_map: ^core.InputActions) { core.register_key_action(input_map, .N, proc(state: ^core.State, user_data: rawptr) { panel := transmute(^core.Panel)user_data panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? if len(panel_state.query_results) > 0 { for result, i in panel_state.query_results { - cursor := panel_state.buffer.history.cursor + cursor := buffer.history.cursor if result.line > cursor.line || (result.line == cursor.line && result.col > cursor.col) { - core.move_cursor_to_location(&panel_state.buffer, result.line, result.col) + core.move_cursor_to_location(buffer, result.line, result.col) break } if i == len(panel_state.query_results)-1 { result := panel_state.query_results[0] - core.move_cursor_to_location(&panel_state.buffer, result.line, result.col) + core.move_cursor_to_location(buffer, result.line, result.col) } } } @@ -439,7 +471,9 @@ file_buffer_input_actions :: proc(input_map: ^core.InputActions) { file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { core.register_key_action(input_map, .ESCAPE, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? state.mode = .Normal; core.reset_input_map(state) @@ -451,14 +485,18 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { // Cursor Movement { core.register_key_action(input_map, .W, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); core.move_cursor_forward_start_of_word(buffer, cursor = &sel_cur.end); }, "move forward one word"); core.register_key_action(input_map, .E, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); @@ -466,7 +504,9 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { }, "move forward to end of word"); core.register_key_action(input_map, .B, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); @@ -474,28 +514,36 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { }, "move backward one word"); core.register_key_action(input_map, .K, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); core.move_cursor_up(buffer, cursor = &sel_cur.end); }, "move up one line"); core.register_key_action(input_map, .J, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); core.move_cursor_down(buffer, cursor = &sel_cur.end); }, "move down one line"); core.register_key_action(input_map, .H, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); core.move_cursor_left(buffer, cursor = &sel_cur.end); }, "move left one char"); core.register_key_action(input_map, .L, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); @@ -503,14 +551,18 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { }, "move right one char"); core.register_ctrl_key_action(input_map, .U, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); core.scroll_file_buffer(buffer, .Up, cursor = &sel_cur.end); }, "scroll buffer up"); core.register_ctrl_key_action(input_map, .D, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? sel_cur := &(buffer.selection.?); @@ -521,7 +573,9 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { // Text Modification { core.register_key_action(input_map, .D, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.push_new_snapshot(&buffer.history) @@ -536,7 +590,9 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { }, "delete selection"); core.register_key_action(input_map, .C, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.push_new_snapshot(&buffer.history) @@ -555,7 +611,9 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { // Copy-Paste { core.register_key_action(input_map, .Y, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.yank_selection(state, buffer) @@ -567,7 +625,9 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { }, "Yank Line"); core.register_key_action(input_map, .P, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.push_new_snapshot(&buffer.history) @@ -586,7 +646,9 @@ file_buffer_visual_actions :: proc(input_map: ^core.InputActions) { file_buffer_text_input_actions :: proc(input_map: ^core.InputActions) { core.register_key_action(input_map, .I, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.push_new_snapshot(&buffer.history) @@ -594,7 +656,9 @@ file_buffer_text_input_actions :: proc(input_map: ^core.InputActions) { sdl2.StartTextInput(); }, "enter insert mode"); core.register_key_action(input_map, .A, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.push_new_snapshot(&buffer.history) @@ -604,14 +668,18 @@ file_buffer_text_input_actions :: proc(input_map: ^core.InputActions) { }, "enter insert mode after character (append)"); core.register_key_action(input_map, .U, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.pop_snapshot(&buffer.history, true) ts.parse_buffer(&buffer.tree, core.tree_sitter_file_buffer_input(buffer)) }, "Undo"); core.register_ctrl_key_action(input_map, .R, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.recover_snapshot(&buffer.history) ts.parse_buffer(&buffer.tree, core.tree_sitter_file_buffer_input(buffer)) @@ -620,33 +688,33 @@ file_buffer_text_input_actions :: proc(input_map: ^core.InputActions) { // TODO: add shift+o to insert newline above current one core.register_key_action(input_map, .O, proc(state: ^core.State, user_data: rawptr) { - buffer := &(&(transmute(^core.Panel)user_data).type.(core.FileBufferPanel)).buffer + panel := transmute(^core.Panel)user_data + panel_state := &panel.type.(core.FileBufferPanel) + buffer := core.get_buffer(state, panel_state.buffer_id).? core.push_new_snapshot(&buffer.history) - if buffer := buffer; buffer != nil { - core.move_cursor_end_of_line(buffer); - - char := core.get_character_at_piece_table_index(core.buffer_piece_table(buffer), buffer.history.cursor.index) - indent := core.get_buffer_indent(buffer) - if char == '{' { - // TODO: update tab to be configurable - indent += 4 - } - - if char != '\n' { - core.move_cursor_right(buffer, stop_at_end = false) - } - - core.insert_content(buffer, []u8{'\n'}) - for i in 0.. core.State { source_font_height = 16, panels = util.make_static_list(core.Panel, 128), + buffers = util.make_static_list(core.FileBuffer, 64), directory = "test_directory", };