From 60c3f9d4567f4a9a564b45e44f681de9fbd441de Mon Sep 17 00:00:00 2001 From: reugenio Date: Sat, 27 Dec 2025 12:24:43 +0100 Subject: [PATCH] refactor(advanced_table): Use table_core.handleEditingKeyboard (DRY) - Remove 160 lines of duplicated keyboard handling code - Use shared table_core.handleEditingKeyboard() for edit buffer operations - Export NavigateDirection from table_core for external use - Keep AdvancedTable-specific navigation logic (cell movement, auto-edit) --- src/widgets/advanced_table/advanced_table.zig | 211 +++++++----------- 1 file changed, 77 insertions(+), 134 deletions(-) diff --git a/src/widgets/advanced_table/advanced_table.zig b/src/widgets/advanced_table/advanced_table.zig index 6f364ae..7f413f8 100644 --- a/src/widgets/advanced_table/advanced_table.zig +++ b/src/widgets/advanced_table/advanced_table.zig @@ -17,6 +17,7 @@ const Context = @import("../../core/context.zig").Context; const Command = @import("../../core/command.zig"); const Layout = @import("../../core/layout.zig"); const Style = @import("../../core/style.zig"); +const table_core = @import("../table_core.zig"); // Re-export types pub const types = @import("types.zig"); @@ -46,6 +47,9 @@ pub const state = @import("state.zig"); pub const AdvancedTableState = state.AdvancedTableState; pub const AdvancedTableResult = state.AdvancedTableResult; +// Re-export table_core types +pub const NavigateDirection = table_core.NavigateDirection; + // ============================================================================= // Public API // ============================================================================= @@ -919,155 +923,94 @@ fn handleEditingKeyboard( ) void { const config = table_schema.config; - // Escape: cancel editing (1st = revert, 2nd = exit without save) - if (ctx.input.keyPressed(.escape)) { - table_state.escape_count += 1; - if (table_state.escape_count >= 2 or table_state.original_value == null) { - // Exit without saving - table_state.stopEditing(); - result.edit_ended = true; - } else { - // Revert to original value - if (table_state.original_value) |orig| { - var format_buf: [128]u8 = undefined; - const text = orig.format(&format_buf); - table_state.startEditing(text); - } - } - return; - } + // Obtener texto original para revert + var orig_format_buf: [128]u8 = undefined; + const original_text: ?[]const u8 = if (table_state.original_value) |orig| + orig.format(&orig_format_buf) + else + null; - // Reset escape count on any other key - table_state.escape_count = 0; + // Usar table_core para procesamiento de teclado (DRY) + const kb_result = table_core.handleEditingKeyboard( + ctx, + &table_state.edit_buffer, + &table_state.edit_len, + &table_state.edit_cursor, + &table_state.escape_count, + original_text, + ); - // Enter: confirm editing - if (ctx.input.keyPressed(.enter)) { - commitEdit(table_state, table_schema, result); + // Si no se procesó ningún evento, salir + if (!kb_result.handled) return; + + // Escape canceló la edición + if (kb_result.cancelled) { table_state.stopEditing(); result.edit_ended = true; return; } - // Tab: confirm and move to next cell - if (ctx.input.keyPressed(.tab) and config.handle_tab) { + // Commit (Enter, Tab, flechas) y navegación + if (kb_result.committed) { commitEdit(table_state, table_schema, result); table_state.stopEditing(); result.edit_ended = true; - // Move to next/prev cell - const shift = ctx.input.modifiers.shift; - const col_count = table_schema.columns.len; - const row_count = table_state.getRowCount(); + // Procesar navegación después de commit + switch (kb_result.navigate) { + .next_cell, .prev_cell => { + if (!config.handle_tab) return; - if (shift) { - // Shift+Tab: move left - if (table_state.selected_col > 0) { - table_state.selectCell( - @intCast(@max(0, table_state.selected_row)), - @intCast(table_state.selected_col - 1), - ); - } else if (table_state.selected_row > 0 and config.wrap_navigation) { - table_state.selectCell( - @intCast(table_state.selected_row - 1), - col_count - 1, - ); - } - } else { - // Tab: move right - if (table_state.selected_col < @as(i32, @intCast(col_count)) - 1) { - table_state.selectCell( - @intCast(@max(0, table_state.selected_row)), - @intCast(table_state.selected_col + 1), - ); - } else if (table_state.selected_row < @as(i32, @intCast(row_count)) - 1 and config.wrap_navigation) { - table_state.selectCell( - @intCast(table_state.selected_row + 1), - 0, - ); - } - } + const col_count = table_schema.columns.len; + const row_count = table_state.getRowCount(); - // Auto-start editing in new cell if editable - const new_col: usize = @intCast(@max(0, table_state.selected_col)); - if (new_col < table_schema.columns.len and table_schema.columns[new_col].editable) { - if (table_state.getRow(@intCast(@max(0, table_state.selected_row)))) |row| { - const value = row.get(table_schema.columns[new_col].name); - var format_buf: [128]u8 = undefined; - const text = value.format(&format_buf); - table_state.startEditing(text); - result.edit_started = true; - } - } - - result.selection_changed = true; - return; - } - - // Cursor movement within edit buffer - if (ctx.input.keyPressed(.left)) { - if (table_state.edit_cursor > 0) { - table_state.edit_cursor -= 1; - } - return; - } - if (ctx.input.keyPressed(.right)) { - if (table_state.edit_cursor < table_state.edit_len) { - table_state.edit_cursor += 1; - } - return; - } - if (ctx.input.keyPressed(.home)) { - table_state.edit_cursor = 0; - return; - } - if (ctx.input.keyPressed(.end)) { - table_state.edit_cursor = table_state.edit_len; - return; - } - - // Backspace: delete char before cursor - if (ctx.input.keyPressed(.backspace)) { - if (table_state.edit_cursor > 0) { - // Shift characters left - var i: usize = table_state.edit_cursor - 1; - while (i < table_state.edit_len - 1) : (i += 1) { - table_state.edit_buffer[i] = table_state.edit_buffer[i + 1]; - } - table_state.edit_len -= 1; - table_state.edit_cursor -= 1; - } - return; - } - - // Delete: delete char at cursor - if (ctx.input.keyPressed(.delete)) { - if (table_state.edit_cursor < table_state.edit_len) { - // Shift characters left - var i: usize = table_state.edit_cursor; - while (i < table_state.edit_len - 1) : (i += 1) { - table_state.edit_buffer[i] = table_state.edit_buffer[i + 1]; - } - table_state.edit_len -= 1; - } - return; - } - - // Character input - if (ctx.input.text_input_len > 0) { - const text = ctx.input.text_input[0..ctx.input.text_input_len]; - for (text) |ch| { - if (ch >= 32 and ch < 127) { - if (table_state.edit_len < types.MAX_EDIT_BUFFER - 1) { - // Shift characters right - var i: usize = table_state.edit_len; - while (i > table_state.edit_cursor) : (i -= 1) { - table_state.edit_buffer[i] = table_state.edit_buffer[i - 1]; + if (kb_result.navigate == .prev_cell) { + // Shift+Tab: move left + if (table_state.selected_col > 0) { + table_state.selectCell( + @intCast(@max(0, table_state.selected_row)), + @intCast(table_state.selected_col - 1), + ); + } else if (table_state.selected_row > 0 and config.wrap_navigation) { + table_state.selectCell( + @intCast(table_state.selected_row - 1), + col_count - 1, + ); + } + } else { + // Tab: move right + if (table_state.selected_col < @as(i32, @intCast(col_count)) - 1) { + table_state.selectCell( + @intCast(@max(0, table_state.selected_row)), + @intCast(table_state.selected_col + 1), + ); + } else if (table_state.selected_row < @as(i32, @intCast(row_count)) - 1 and config.wrap_navigation) { + table_state.selectCell( + @intCast(table_state.selected_row + 1), + 0, + ); } - table_state.edit_buffer[table_state.edit_cursor] = ch; - table_state.edit_len += 1; - table_state.edit_cursor += 1; } - } + + // Auto-start editing in new cell if editable + const new_col: usize = @intCast(@max(0, table_state.selected_col)); + if (new_col < table_schema.columns.len and table_schema.columns[new_col].editable) { + if (table_state.getRow(@intCast(@max(0, table_state.selected_row)))) |row| { + const value = row.get(table_schema.columns[new_col].name); + var format_buf: [128]u8 = undefined; + const text = value.format(&format_buf); + table_state.startEditing(text); + result.edit_started = true; + } + } + + result.selection_changed = true; + }, + .next_row, .prev_row => { + // Enter o flechas arriba/abajo: solo commit, sin navegación adicional aquí + // (La navegación entre filas se maneja en otro lugar si es necesario) + }, + .none => {}, } } }