Skip to content

Commit dfb7d08

Browse files
TimelordUKclaude
andcommitted
Merge feat/buffer-system: Phase 1 buffer migration complete
This merge brings in significant improvements to the TUI architecture: Buffer System Migration (Phase 1): - Introduced BufferAPI trait for abstraction - Created Buffer struct with independent state management - Added BufferManager for multi-buffer support - Migrated simple fields (edit_mode, case_insensitive, etc.) - Added buffer debug dump to F5 output Fixes and Improvements: - Fixed case_insensitive icon not showing in status line - Fixed column search text not rendering properly - Fixed fuzzy filter and search modes to preserve SQL query - Fixed fuzzy filter status line indicator persistence - Added command history deduplication - Auto-clean history file on startup - Comprehensive test suite for complex queries The buffer system now provides a solid foundation for: - Multiple file/tab support - Proper state isolation between buffers - Easier testing and maintenance - Future migration of complex state (Phase 2) All search/filter modes now correctly preserve the SQL query and provide proper visual feedback. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2 parents 8d305d0 + 5fc96f5 commit dfb7d08

20 files changed

Lines changed: 2673 additions & 77 deletions

column-search.cast

Lines changed: 372 additions & 0 deletions
Large diffs are not rendered by default.

column-search.gif

8.77 MB
Loading

sql-cli/MIGRATION_AUDIT.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Buffer Migration Audit
2+
3+
This document tracks the migration of fields from EnhancedTuiApp to Buffer via BufferAPI.
4+
5+
## Migration Categories
6+
7+
### ✅ Already in Buffer (via BufferAPI)
8+
These fields already exist in Buffer and have BufferAPI methods:
9+
10+
- [x] `mode: AppMode``get_mode()`, `set_mode()`
11+
- [x] `status_message: String``get_status_message()`, `set_status_message()`
12+
- [x] `results: Option<QueryResponse>``get_results()`, `set_results()`
13+
- [x] `table_state: TableState``get_selected_row()`, `set_selected_row()`
14+
- [x] `input: Input``get_input_value()`, `set_input_value()`, etc.
15+
- [x] `current_column: usize``get_current_column()`, `set_current_column()`
16+
- [x] `scroll_offset: (usize, usize)``get_scroll_offset()`, `set_scroll_offset()`
17+
- [x] `pinned_columns: Vec<usize>``get_pinned_columns()`, `add_pinned_column()`, etc.
18+
- [x] `compact_mode: bool``is_compact_mode()`, `set_compact_mode()`
19+
- [x] `show_row_numbers: bool``is_show_row_numbers()`, `set_show_row_numbers()`
20+
- [x] `filter_state: FilterState``get_filter_pattern()`, `is_filter_active()`, etc.
21+
- [x] `search_state: SearchState``get_search_pattern()`, `get_search_matches()`, etc.
22+
- [x] `sort_state: SortState``get_sort_column()`, `get_sort_order()`, etc.
23+
- [x] `csv_client: Option<CsvApiClient>``get_csv_client()`, `get_csv_client_mut()`
24+
- [x] `csv_mode: bool``is_csv_mode()`
25+
- [x] `csv_table_name: String``get_table_name()`
26+
- [x] `filtered_data: Option<Vec<Vec<String>>>``get_filtered_data()`, `set_filtered_data()`
27+
28+
### ✅ Phase 1: Simple Fields (COMPLETED)
29+
These are straightforward to migrate and test:
30+
31+
- [x] `edit_mode: EditMode` - How the editor is being used (single/multi-line)
32+
- [x] `last_results_row: Option<usize>` - Position preservation
33+
- [x] `last_scroll_offset: (usize, usize)` - Position preservation
34+
- [x] `case_insensitive: bool` - Search/filter behavior
35+
- [x] `last_query_source: Option<String>` - Track where query came from
36+
37+
### 🔄 Phase 2: Buffer-Specific Complex State
38+
These need to move but require more care:
39+
40+
- [ ] `textarea: TextArea<'static>` - Multi-line editor state
41+
- [ ] `fuzzy_filter_state: FuzzyFilterState` - Fuzzy search state
42+
- [ ] `column_search_state: ColumnSearchState` - Column search functionality
43+
- [ ] `column_widths: Vec<u16>` - Display formatting
44+
- [ ] `column_stats: Option<ColumnStatistics>` - Statistics for current column
45+
- [ ] `cached_data: Option<Vec<serde_json::Value>>` - Cached query results
46+
- [ ] `cache_mode: bool` - Whether caching is active
47+
- [ ] `undo_stack: Vec<(String, usize)>` - Undo history
48+
- [ ] `redo_stack: Vec<(String, usize)>` - Redo history
49+
- [ ] `kill_ring: String` - Vim-style yank buffer
50+
- [ ] `viewport_lock: bool` - Display behavior
51+
- [ ] `viewport_lock_row: Option<usize>` - Display behavior
52+
- [ ] `jump_to_row_input: String` - Jump command input
53+
- [ ] `last_visible_rows: usize` - Display tracking
54+
55+
### 🚫 Should Stay in TUI (Global State)
56+
These are truly global and shouldn't be in buffers:
57+
58+
- `api_client: ApiClient` - Global API connection
59+
- `sql_parser: SqlParser` - Global parser
60+
- `hybrid_parser: HybridParser` - Global parser
61+
- `config: Config` - User configuration
62+
- `command_history: CommandHistory` - Global command history
63+
- `sql_highlighter: SqlHighlighter` - Syntax highlighting
64+
- `query_cache: Option<QueryCache>` - Global cache
65+
- `show_help: bool` - UI state
66+
- `help_scroll: u16` - UI state
67+
- `debug_text: String` - Debug UI
68+
- `debug_scroll: u16` - Debug UI
69+
- `input_scroll_offset: u16` - UI display
70+
- `selection_mode: SelectionMode` - Global UI preference
71+
- `yank_mode: Option<char>` - Global clipboard state
72+
- `last_yanked: Option<(String, String)>` - Global clipboard
73+
- `completion_state: CompletionState` - UI helper
74+
- `history_state: HistoryState` - UI helper
75+
- `buffer_manager: Option<BufferManager>` - The manager itself
76+
- `current_buffer_name: Option<String>` - Current buffer tracking
77+
78+
## Migration Strategy
79+
80+
### Step 1: Create Compatibility Layer
81+
For each field we want to migrate, create a method that:
82+
1. Checks if buffer_manager exists
83+
2. If yes, use BufferAPI
84+
3. If no, use direct field access
85+
86+
Example:
87+
```rust
88+
fn get_edit_mode(&self) -> EditMode {
89+
if let Some(buffer) = self.get_current_buffer() {
90+
buffer.get_edit_mode()
91+
} else {
92+
self.edit_mode
93+
}
94+
}
95+
```
96+
97+
### Step 2: Update All References
98+
Search for all direct field accesses and replace with compatibility methods:
99+
- `self.edit_mode``self.get_edit_mode()`
100+
- `self.edit_mode = x``self.set_edit_mode(x)`
101+
102+
### Step 3: Test After Each Migration
103+
Run the TUI and verify:
104+
1. Basic navigation works
105+
2. Editing works
106+
3. Filtering/searching works
107+
4. No crashes or unexpected behavior
108+
109+
### Step 4: Move Field to Buffer
110+
Once all references use the compatibility layer:
111+
1. Add field to Buffer struct
112+
2. Add to BufferAPI trait
113+
3. Implement in Buffer
114+
4. Remove from EnhancedTuiApp
115+
116+
## Progress Tracking
117+
118+
### Phase 1 Checklist (Simple Fields)
119+
- [ ] Add `edit_mode` to BufferAPI
120+
- [ ] Create `get_edit_mode()` / `set_edit_mode()` compatibility methods
121+
- [ ] Update all `self.edit_mode` references
122+
- [ ] Test TUI functionality
123+
- [ ] Move field to Buffer
124+
- [ ] Repeat for other Phase 1 fields
125+
126+
### Testing Checklist
127+
After each field migration:
128+
- [ ] Can open a CSV file
129+
- [ ] Can type and execute queries
130+
- [ ] Can navigate results
131+
- [ ] Can filter results
132+
- [ ] Can search in results
133+
- [ ] Can yank/copy data
134+
- [ ] No crashes or panics
135+
136+
## Notes
137+
138+
- We can merge to master at any point - the compatibility layer ensures nothing breaks
139+
- Each field migration is independent - we can do them one at a time
140+
- If something goes wrong, we can easily revert a single field migration
141+
- The goal is gradual, safe migration, not speed

sql-cli/column-search-final.cast

Whitespace-only changes.

0 commit comments

Comments
 (0)