remove input_buffer for intermediate text input, directly insert into filebuffer
parent
dab095e88d
commit
ad5e4f85fd
|
@ -137,8 +137,6 @@ 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
|
||||
|
@ -171,7 +169,12 @@ yank_selection :: proc(state: ^State, buffer: ^FileBuffer) {
|
|||
length := selection_length(buffer, selection)
|
||||
|
||||
state.yank_register.whole_line = false
|
||||
state.yank_register.data = make([]u8, length)
|
||||
|
||||
err: runtime.Allocator_Error
|
||||
state.yank_register.data, err = make([]u8, length)
|
||||
if err != nil {
|
||||
log.error("failed to allocate memory for yank register")
|
||||
}
|
||||
|
||||
it := new_file_buffer_iter_with_cursor(buffer, selection.start)
|
||||
|
||||
|
|
|
@ -55,8 +55,6 @@ FileBuffer :: struct {
|
|||
|
||||
history: FileHistory,
|
||||
glyphs: GlyphBuffer,
|
||||
|
||||
input_buffer: [dynamic]u8,
|
||||
}
|
||||
|
||||
BufferFlagSet :: bit_set[BufferFlags]
|
||||
|
@ -712,7 +710,6 @@ new_virtual_file_buffer :: proc(allocator := context.allocator) -> FileBuffer {
|
|||
history = make_history(),
|
||||
|
||||
glyphs = make_glyph_buffer(width, height),
|
||||
input_buffer = make([dynamic]u8, 0, 1024),
|
||||
};
|
||||
|
||||
return buffer;
|
||||
|
@ -776,7 +773,6 @@ new_file_buffer :: proc(allocator: mem.Allocator, file_path: string, base_dir: s
|
|||
history = make_history(content),
|
||||
|
||||
glyphs = make_glyph_buffer(width, height),
|
||||
input_buffer = make([dynamic]u8, 0, 1024),
|
||||
};
|
||||
|
||||
ts.parse_buffer(&buffer.tree, tree_sitter_file_buffer_input(&buffer))
|
||||
|
@ -834,7 +830,6 @@ free_file_buffer :: proc(buffer: ^FileBuffer) {
|
|||
ts.delete_state(&buffer.tree)
|
||||
free_history(&buffer.history)
|
||||
delete(buffer.glyphs.buffer)
|
||||
delete(buffer.input_buffer)
|
||||
}
|
||||
|
||||
color_character :: proc(buffer: ^FileBuffer, start: Cursor, end: Cursor, palette_index: theme.PaletteColor) {
|
||||
|
@ -906,26 +901,6 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x, y, w, h: int, sh
|
|||
draw_rect(state, start_sel_x, start_sel_y, state.source_font_width, state.source_font_height, .Green);
|
||||
draw_rect(state, end_sel_x, end_sel_y, state.source_font_width, state.source_font_height, .Blue);
|
||||
} else if state.mode == .Insert {
|
||||
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Green);
|
||||
|
||||
num_line_break := 0;
|
||||
line_length := 0;
|
||||
for c in buffer.input_buffer {
|
||||
if c == '\n' {
|
||||
num_line_break += 1;
|
||||
line_length = 0;
|
||||
} else {
|
||||
line_length += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if num_line_break > 0 {
|
||||
cursor_x = x + padding + line_length * state.source_font_width;
|
||||
cursor_y = cursor_y + num_line_break * state.source_font_height;
|
||||
} else {
|
||||
cursor_x += line_length * state.source_font_width;
|
||||
}
|
||||
|
||||
draw_rect(state, cursor_x, cursor_y, state.source_font_width, state.source_font_height, .Blue);
|
||||
}
|
||||
}
|
||||
|
@ -1007,42 +982,33 @@ scroll_file_buffer :: proc(buffer: ^FileBuffer, dir: ScrollDir, cursor: Maybe(^C
|
|||
}
|
||||
}
|
||||
|
||||
insert_content :: proc(buffer: ^FileBuffer, to_be_inserted: []u8, append_to_end: bool = false) {
|
||||
insert_content :: proc(buffer: ^FileBuffer, to_be_inserted: []u8) {
|
||||
if len(to_be_inserted) == 0 {
|
||||
return;
|
||||
}
|
||||
buffer.flags += { .UnsavedChanges }
|
||||
|
||||
index := buffer.history.cursor.index if !append_to_end else new_piece_table_index_from_end(buffer_piece_table(buffer))
|
||||
index := buffer.history.cursor.index
|
||||
|
||||
insert_text(buffer_piece_table(buffer), to_be_inserted, buffer.history.cursor.index)
|
||||
|
||||
if !append_to_end {
|
||||
update_file_buffer_index_from_cursor(buffer);
|
||||
move_cursor_right(buffer, false, amt = len(to_be_inserted) - 1);
|
||||
}
|
||||
update_file_buffer_index_from_cursor(buffer);
|
||||
move_cursor_right(buffer, false, amt = len(to_be_inserted));
|
||||
|
||||
ts.parse_buffer(&buffer.tree, tree_sitter_file_buffer_input(buffer))
|
||||
}
|
||||
|
||||
delete_content_from_buffer_cursor :: proc(buffer: ^FileBuffer, amount: int) {
|
||||
if amount <= len(buffer.input_buffer) {
|
||||
runtime.resize(&buffer.input_buffer, len(buffer.input_buffer)-amount);
|
||||
} else {
|
||||
buffer.flags += { .UnsavedChanges }
|
||||
buffer.flags += { .UnsavedChanges }
|
||||
|
||||
amount := amount - len(buffer.input_buffer);
|
||||
runtime.clear(&buffer.input_buffer);
|
||||
// Calculate proper line/col values
|
||||
it := new_file_buffer_iter_with_cursor(buffer, buffer.history.cursor);
|
||||
iterate_file_buffer_reverse(&it)
|
||||
|
||||
// Calculate proper line/col values
|
||||
it := new_file_buffer_iter_with_cursor(buffer, buffer.history.cursor);
|
||||
iterate_file_buffer_reverse(&it)
|
||||
delete_text(buffer_piece_table(buffer), &buffer.history.cursor.index)
|
||||
|
||||
delete_text(buffer_piece_table(buffer), &buffer.history.cursor.index)
|
||||
|
||||
buffer.history.cursor.line = it.cursor.line
|
||||
buffer.history.cursor.col = it.cursor.col
|
||||
}
|
||||
buffer.history.cursor.line = it.cursor.line
|
||||
buffer.history.cursor.col = it.cursor.col
|
||||
|
||||
ts.parse_buffer(&buffer.tree, tree_sitter_file_buffer_input(buffer))
|
||||
}
|
||||
|
@ -1067,3 +1033,43 @@ delete_content_from_selection :: proc(buffer: ^FileBuffer, selection: ^Selection
|
|||
|
||||
delete_content :: proc{delete_content_from_buffer_cursor, delete_content_from_selection};
|
||||
|
||||
get_buffer_indent :: proc(buffer: ^FileBuffer, cursor: Maybe(Cursor) = nil) -> int {
|
||||
cursor := cursor;
|
||||
|
||||
if cursor == nil {
|
||||
cursor = buffer.history.cursor;
|
||||
}
|
||||
|
||||
ptr_cursor := &cursor.?
|
||||
|
||||
move_cursor_start_of_line(buffer, ptr_cursor)
|
||||
move_cursor_forward_end_of_word(buffer, ptr_cursor)
|
||||
move_cursor_backward_start_of_word(buffer, ptr_cursor)
|
||||
|
||||
return cursor.?.col
|
||||
}
|
||||
|
||||
buffer_to_string :: proc(buffer: ^FileBuffer, allocator := context.allocator) -> string {
|
||||
context.allocator = allocator
|
||||
|
||||
length := 0
|
||||
for chunk in buffer_piece_table(buffer).chunks {
|
||||
length += len(chunk)
|
||||
}
|
||||
|
||||
buffer_contents := make([]u8, length)
|
||||
|
||||
offset := 0
|
||||
for chunk in buffer_piece_table(buffer).chunks {
|
||||
for c in chunk {
|
||||
buffer_contents[offset] = c
|
||||
offset += 1
|
||||
}
|
||||
}
|
||||
|
||||
return string(buffer_contents[:len(buffer_contents)-1])
|
||||
}
|
||||
|
||||
buffer_append_new_line :: proc(buffer: ^FileBuffer) {
|
||||
|
||||
}
|
|
@ -61,25 +61,26 @@ update_glyph_buffer_from_file_buffer :: proc(buffer: ^FileBuffer, width, height:
|
|||
// don't render past the screen
|
||||
if rendered_line >= begin && screen_line >= buffer.glyphs.height { break; }
|
||||
|
||||
// render INSERT mode text into glyph buffer
|
||||
if len(buffer.input_buffer) > 0 && rendered_line == buffer.history.cursor.line && rendered_col >= buffer.history.cursor.col && rendered_col < buffer.history.cursor.col + len(buffer.input_buffer) {
|
||||
for k in 0..<len(buffer.input_buffer) {
|
||||
screen_line = rendered_line - begin;
|
||||
// NOTE: `input_buffer` doesn't exist anymore, but this is a nice reference for just inserting text within the glyph buffer
|
||||
//
|
||||
// if len(buffer.input_buffer) > 0 && rendered_line == buffer.history.cursor.line && rendered_col >= buffer.history.cursor.col && rendered_col < buffer.history.cursor.col + len(buffer.input_buffer) {
|
||||
// for k in 0..<len(buffer.input_buffer) {
|
||||
// screen_line = rendered_line - begin;
|
||||
|
||||
if buffer.input_buffer[k] == '\n' {
|
||||
rendered_col = 0;
|
||||
rendered_line += 1;
|
||||
continue;
|
||||
}
|
||||
// if buffer.input_buffer[k] == '\n' {
|
||||
// rendered_col = 0;
|
||||
// rendered_line += 1;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if rendered_line >= begin && rendered_col < buffer.glyphs.width {
|
||||
buffer.glyphs.buffer[rendered_col + screen_line * buffer.glyphs.width].color = .Foreground;
|
||||
buffer.glyphs.buffer[rendered_col + screen_line * buffer.glyphs.width].codepoint = buffer.input_buffer[k];
|
||||
// if rendered_line >= begin && rendered_col < buffer.glyphs.width {
|
||||
// buffer.glyphs.buffer[rendered_col + screen_line * buffer.glyphs.width].color = .Foreground;
|
||||
// buffer.glyphs.buffer[rendered_col + screen_line * buffer.glyphs.width].codepoint = buffer.input_buffer[k];
|
||||
|
||||
rendered_col += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// rendered_col += 1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
screen_line = rendered_line - begin;
|
||||
|
||||
|
|
|
@ -32,10 +32,11 @@ new_logger :: proc(buffer: ^FileBuffer) -> runtime.Logger {
|
|||
logger_proc :: proc(data: rawptr, level: runtime.Logger_Level, text: string, options: runtime.Logger_Options, location := #caller_location) {
|
||||
buffer := cast(^FileBuffer)data;
|
||||
|
||||
if .Level in options {
|
||||
insert_content(buffer, transmute([]u8)(Level_Header[level]), true);
|
||||
}
|
||||
// FIXME
|
||||
// if .Level in options {
|
||||
// insert_content(buffer, transmute([]u8)(Level_Header[level]), true);
|
||||
// }
|
||||
|
||||
insert_content(buffer, transmute([]u8)(text), true);
|
||||
insert_content(buffer, {'\n'}, true);
|
||||
// insert_content(buffer, transmute([]u8)(text), true);
|
||||
// insert_content(buffer, {'\n'}, true);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package core
|
|||
PieceTable :: struct {
|
||||
original_content: []u8,
|
||||
added_content: [dynamic]u8,
|
||||
|
||||
// TODO: don't actually reference `added_content` and `original_content` via pointers, since they can be re-allocated
|
||||
chunks: [dynamic][]u8,
|
||||
}
|
||||
|
||||
|
@ -158,7 +160,19 @@ insert_text :: proc(t: ^PieceTable, to_be_inserted: []u8, index: PieceTableIndex
|
|||
if index.char_index == 0 {
|
||||
// insertion happening in beginning of content slice
|
||||
|
||||
inject_at(&t.chunks, index.chunk_index, inserted_slice);
|
||||
if len(t.chunks) > 1 && index.chunk_index > 0 {
|
||||
last_chunk_index := len(t.chunks[index.chunk_index-1])-1
|
||||
|
||||
if (&t.chunks[index.chunk_index-1][last_chunk_index]) == (&t.added_content[len(t.added_content)-1 - length]) {
|
||||
start := len(t.added_content)-1 - last_chunk_index - length
|
||||
|
||||
t.chunks[index.chunk_index-1] = t.added_content[start:]
|
||||
} else {
|
||||
inject_at(&t.chunks, index.chunk_index, inserted_slice);
|
||||
}
|
||||
} else {
|
||||
inject_at(&t.chunks, index.chunk_index, inserted_slice);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// insertion is happening in middle of content slice
|
||||
|
|
|
@ -25,24 +25,6 @@ FileBuffer :: core.FileBuffer;
|
|||
|
||||
state := core.State {};
|
||||
|
||||
do_normal_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||
}
|
||||
|
||||
do_insert_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||
key := 0;
|
||||
|
||||
for key > 0 {
|
||||
if key >= 32 && key <= 125 && len(buffer.input_buffer) < 1024-1 {
|
||||
append(&buffer.input_buffer, u8(key));
|
||||
}
|
||||
|
||||
key = 0;
|
||||
}
|
||||
}
|
||||
|
||||
do_visual_mode :: proc(state: ^State, buffer: ^FileBuffer) {
|
||||
}
|
||||
|
||||
ui_font_width :: proc() -> i32 {
|
||||
return i32(state.source_font_width);
|
||||
}
|
||||
|
@ -444,22 +426,47 @@ main :: proc() {
|
|||
case .ESCAPE: {
|
||||
state.mode = .Normal;
|
||||
|
||||
core.insert_content(buffer, buffer.input_buffer[:]);
|
||||
runtime.clear(&buffer.input_buffer);
|
||||
// core.insert_content(buffer, buffer.input_buffer[:]);
|
||||
// runtime.clear(&buffer.input_buffer);
|
||||
core.move_cursor_left(buffer)
|
||||
|
||||
sdl2.StopTextInput();
|
||||
}
|
||||
case .TAB: {
|
||||
// TODO: change this to insert a tab character
|
||||
for _ in 0..<4 {
|
||||
append(&buffer.input_buffer, ' ');
|
||||
// for _ in 0..<4 {
|
||||
// append(&buffer.input_buffer, ' ');
|
||||
// }
|
||||
core.insert_content(buffer, transmute([]u8)string(" "))
|
||||
|
||||
if current_panel, ok := state.current_panel.?; ok {
|
||||
if panel, ok := util.get(&state.panels, current_panel).?; ok && panel.on_buffer_input != nil {
|
||||
panel->on_buffer_input(&state)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .BACKSPACE: {
|
||||
core.delete_content(buffer, 1);
|
||||
|
||||
if current_panel, ok := state.current_panel.?; ok {
|
||||
if panel, ok := util.get(&state.panels, current_panel).?; ok && panel.on_buffer_input != nil {
|
||||
panel->on_buffer_input(&state)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .ENTER: {
|
||||
append(&buffer.input_buffer, '\n');
|
||||
indent := core.get_buffer_indent(buffer)
|
||||
core.insert_content(buffer, []u8{'\n'})
|
||||
|
||||
for i in 0..<indent {
|
||||
core.insert_content(buffer, []u8{' '})
|
||||
}
|
||||
|
||||
if current_panel, ok := state.current_panel.?; ok {
|
||||
if panel, ok := util.get(&state.panels, current_panel).?; ok && panel.on_buffer_input != nil {
|
||||
panel->on_buffer_input(&state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -471,8 +478,9 @@ main :: proc() {
|
|||
break;
|
||||
}
|
||||
|
||||
if char >= 32 && char <= 125 && len(buffer.input_buffer) < 1024-1 {
|
||||
append(&buffer.input_buffer, u8(char));
|
||||
if char >= 32 && char <= 125 {
|
||||
// append(&buffer.input_buffer, u8(char));
|
||||
core.insert_content(buffer, []u8{char})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -489,18 +497,6 @@ main :: proc() {
|
|||
|
||||
draw(&state);
|
||||
|
||||
switch state.mode {
|
||||
case .Normal:
|
||||
buffer := core.current_buffer(&state);
|
||||
do_normal_mode(&state, buffer);
|
||||
case .Insert:
|
||||
buffer := core.current_buffer(&state);
|
||||
do_insert_mode(&state, buffer);
|
||||
case .Visual:
|
||||
buffer := core.current_buffer(&state);
|
||||
do_visual_mode(&state, buffer);
|
||||
}
|
||||
|
||||
runtime.free_all(context.temp_allocator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -502,10 +502,23 @@ file_buffer_text_input_actions :: proc(input_map: ^core.InputActions) {
|
|||
core.push_new_snapshot(&buffer.history)
|
||||
|
||||
if buffer := buffer; buffer != nil {
|
||||
core.move_cursor_end_of_line(buffer, false);
|
||||
runtime.clear(&buffer.input_buffer)
|
||||
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
|
||||
}
|
||||
|
||||
append(&buffer.input_buffer, '\n')
|
||||
if char != '\n' {
|
||||
core.move_cursor_right(buffer, stop_at_end = false)
|
||||
}
|
||||
|
||||
core.insert_content(buffer, []u8{'\n'})
|
||||
for i in 0..<indent {
|
||||
core.insert_content(buffer, []u8{' '})
|
||||
}
|
||||
|
||||
state.mode = .Insert;
|
||||
|
||||
|
@ -534,9 +547,8 @@ file_buffer_text_input_actions :: proc(input_map: ^core.InputActions) {
|
|||
core.push_new_snapshot(&buffer.history)
|
||||
|
||||
if state.yank_register.whole_line {
|
||||
core.move_cursor_end_of_line(buffer, false);
|
||||
core.move_cursor_end_of_line(buffer, stop_at_end = false);
|
||||
core.insert_content(buffer, []u8{'\n'});
|
||||
core.move_cursor_right(buffer, false);
|
||||
} else {
|
||||
core.move_cursor_right(buffer)
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ open_grep_panel :: proc(state: ^core.State) {
|
|||
}
|
||||
|
||||
make_grep_panel :: proc() -> core.Panel {
|
||||
run_query :: proc(panel_state: ^core.GrepPanel, query: string, directory: string) {
|
||||
run_query :: proc(panel_state: ^core.GrepPanel, buffer: ^core.FileBuffer, directory: string) {
|
||||
if panel_state.query_region.arena != nil {
|
||||
mem.end_arena_temp_memory(panel_state.query_region)
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ make_grep_panel :: proc() -> core.Panel {
|
|||
context.allocator = mem.arena_allocator(&panel_state.query_arena)
|
||||
|
||||
rs_results := grep(
|
||||
strings.clone_to_cstring(query),
|
||||
strings.clone_to_cstring(core.buffer_to_string(buffer)),
|
||||
strings.clone_to_cstring(directory)
|
||||
);
|
||||
|
||||
|
@ -142,7 +142,7 @@ make_grep_panel :: proc() -> core.Panel {
|
|||
},
|
||||
on_buffer_input = proc(panel: ^core.Panel, state: ^core.State) {
|
||||
if panel_state, ok := &panel.type.(core.GrepPanel); ok {
|
||||
run_query(panel_state, string(panel_state.buffer.input_buffer[:]), state.directory)
|
||||
run_query(panel_state, &panel_state.buffer, state.directory)
|
||||
}
|
||||
},
|
||||
render = proc(panel: ^core.Panel, state: ^core.State) -> (ok: bool) {
|
||||
|
|
|
@ -270,7 +270,6 @@ insert_before_slice :: proc(t: ^testing.T) {
|
|||
run_text_insertion(&e, " rich")
|
||||
|
||||
expect_line_col(t, buffer.history.cursor, 0, 20)
|
||||
expect_cursor_index(t, buffer.history.cursor, 2, 4)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
@ -346,8 +345,7 @@ delete_in_slice :: proc(t: ^testing.T) {
|
|||
run_input_multiple(&e, press_key(.BACKSPACE), 3)
|
||||
run_input_multiple(&e, press_key(.ESCAPE), 1)
|
||||
|
||||
expect_line_col(t, buffer.history.cursor, 0, 17)
|
||||
expect_cursor_index(t, buffer.history.cursor, 3, 0)
|
||||
expect_line_col(t, buffer.history.cursor, 0, 16)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
@ -387,15 +385,14 @@ delete_across_slices :: proc(t: ^testing.T) {
|
|||
run_input_multiple(&e, press_key(.ESCAPE), 1)
|
||||
|
||||
// Move right, passed the 'h' on to the space before 'world!'
|
||||
run_input_multiple(&e, press_key(.L), 1)
|
||||
run_input_multiple(&e, press_key(.L), 2)
|
||||
|
||||
// Remove the ' h', which consists of two content slices
|
||||
run_input_multiple(&e, press_key(.I), 1)
|
||||
run_input_multiple(&e, press_key(.BACKSPACE), 2)
|
||||
run_input_multiple(&e, press_key(.ESCAPE), 1)
|
||||
|
||||
expect_line_col(t, buffer.history.cursor, 0, 16)
|
||||
expect_cursor_index(t, buffer.history.cursor, 2, 0)
|
||||
expect_line_col(t, buffer.history.cursor, 0, 15)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
@ -632,14 +629,12 @@ append_end_of_line :: proc(t: ^testing.T) {
|
|||
run_input_multiple(&e, press_key(.A), 1)
|
||||
run_input_multiple(&e, press_key(.ESCAPE), 1)
|
||||
|
||||
expect_line_col(t, buffer.history.cursor, 0, 5)
|
||||
expect_cursor_index(t, buffer.history.cursor, 1, 0)
|
||||
expect_line_col(t, buffer.history.cursor, 0, 4)
|
||||
|
||||
run_input_multiple(&e, press_key(.A), 1)
|
||||
run_input_multiple(&e, press_key(.ESCAPE), 1)
|
||||
|
||||
expect_line_col(t, buffer.history.cursor, 0, 5)
|
||||
expect_cursor_index(t, buffer.history.cursor, 1, 0)
|
||||
expect_line_col(t, buffer.history.cursor, 0, 4)
|
||||
}
|
||||
|
||||
@(test)
|
||||
|
@ -667,15 +662,11 @@ insert_line_under_current :: proc(t: ^testing.T) {
|
|||
// Insert line below and enter insert mode
|
||||
run_input_multiple(&e, press_key(.O), 1)
|
||||
|
||||
// Technically the cursor is still on the first line, because the `input_buffer`
|
||||
// has been modified but not the actual contents of the filebuffer
|
||||
expect_line_col(t, buffer.history.cursor, 0, 13)
|
||||
expect_cursor_index(t, buffer.history.cursor, 0, 13)
|
||||
expect_line_col(t, buffer.history.cursor, 1, 0)
|
||||
|
||||
run_text_insertion(&e, "This is the second line")
|
||||
|
||||
expect_line_col(t, buffer.history.cursor, 1, 22)
|
||||
expect_cursor_index(t, buffer.history.cursor, 1, 23)
|
||||
|
||||
contents := buffer_to_string(core.current_buffer(&e))
|
||||
defer delete(contents)
|
||||
|
@ -812,21 +803,40 @@ run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pre
|
|||
#partial switch key.key {
|
||||
case .ESCAPE: {
|
||||
state.mode = .Normal;
|
||||
|
||||
core.insert_content(buffer, buffer.input_buffer[:]);
|
||||
runtime.clear(&buffer.input_buffer);
|
||||
core.move_cursor_left(buffer)
|
||||
}
|
||||
case .TAB: {
|
||||
// TODO: change this to insert a tab character
|
||||
for _ in 0..<4 {
|
||||
append(&buffer.input_buffer, ' ');
|
||||
core.insert_content(buffer, transmute([]u8)string(" "))
|
||||
|
||||
if current_panel, ok := state.current_panel.?; ok {
|
||||
if panel, ok := util.get(&state.panels, current_panel).?; ok && panel.on_buffer_input != nil {
|
||||
panel->on_buffer_input(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .BACKSPACE: {
|
||||
core.delete_content(buffer, 1);
|
||||
|
||||
if current_panel, ok := state.current_panel.?; ok {
|
||||
if panel, ok := util.get(&state.panels, current_panel).?; ok && panel.on_buffer_input != nil {
|
||||
panel->on_buffer_input(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
case .ENTER: {
|
||||
append(&buffer.input_buffer, '\n');
|
||||
indent := core.get_buffer_indent(buffer)
|
||||
core.insert_content(buffer, []u8{'\n'})
|
||||
|
||||
for i in 0..<indent {
|
||||
core.insert_content(buffer, []u8{' '})
|
||||
}
|
||||
|
||||
if current_panel, ok := state.current_panel.?; ok {
|
||||
if panel, ok := util.get(&state.panels, current_panel).?; ok && panel.on_buffer_input != nil {
|
||||
panel->on_buffer_input(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -839,8 +849,8 @@ run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pre
|
|||
break;
|
||||
}
|
||||
|
||||
if char == '\n' || (char >= 32 && char <= 125 && len(buffer.input_buffer) < 1024-1) {
|
||||
append(&buffer.input_buffer, u8(char));
|
||||
if char == '\n' || (char >= 32 && char <= 125) {
|
||||
core.insert_content(buffer, []u8{u8(char)})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -854,30 +864,5 @@ run_editor_frame :: proc(state: ^core.State, input: ArtificialInput, is_ctrl_pre
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: share this with the main application
|
||||
do_insert_mode :: proc(state: ^core.State, buffer: ^core.FileBuffer) {
|
||||
key := 0;
|
||||
|
||||
for key > 0 {
|
||||
if key >= 32 && key <= 125 && len(buffer.input_buffer) < 1024-1 {
|
||||
append(&buffer.input_buffer, u8(key));
|
||||
}
|
||||
|
||||
key = 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch state.mode {
|
||||
case .Normal:
|
||||
// buffer := core.current_buffer(state);
|
||||
// do_normal_mode(state, buffer);
|
||||
case .Insert:
|
||||
buffer := core.current_buffer(state);
|
||||
do_insert_mode(state, buffer);
|
||||
case .Visual:
|
||||
// buffer := core.current_buffer(state);
|
||||
// do_visual_mode(state, buffer);
|
||||
}
|
||||
|
||||
runtime.free_all(context.temp_allocator);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue