sql-cli 1.73.1

SQL query tool for CSV/JSON with both interactive TUI and non-interactive CLI modes - perfect for exploration and automation
Documentation
# Trait Extraction Analysis: Navigation vs Column Operations

## Dependency Comparison

### Navigation Methods Dependencies

**Methods**: `next_row`, `previous_row`, `goto_first_row`, `goto_last_row`, `page_up`, `page_down`, etc.

**Dependencies**:
1. `self.viewport_manager` (RefCell) - For navigation
2. `self.buffer_mut()` - For setting selected row & scroll offset
3. `self.state_container.navigation_mut()` - For updating navigation state
4. `self.get_row_count()` - Helper method (for goto_first/last)
5. `apply_row_navigation_result()` - Helper method

**Helper Method Dependencies** (`apply_row_navigation_result`):
- `buffer_mut().set_selected_row()`
- `buffer_mut().set_scroll_offset()`
- `state_container.navigation_mut()`

### Column Operations Dependencies

**Methods**: `hide_current_column`, `unhide_all_columns`, `move_current_column_left`, `move_current_column_right`

**Dependencies**:
1. `self.viewport_manager` (RefCell) - For column operations
2. `self.buffer().get_mode()` - Mode check
3. `self.buffer_mut()` - For setting dataview & status
4. `self.state_container.navigation_mut()` - For updating column position
5. `apply_column_operation_result()` - Helper method

**Helper Method Dependencies** (`apply_column_operation_result`):
- `buffer_mut().set_status_message()`
- `buffer_mut().set_dataview()`
- `buffer_mut().set_current_column()`
- `buffer().get_dataview()` - For pinned column count
- `state_container.navigation_mut()`

## Comparison Results

| Aspect | Navigation | Column Operations |
|--------|------------|-------------------|
| **Number of methods** | 9 methods | 4 methods |
| **External dependencies** | 3 (viewport, buffer, state) | 4 (viewport, buffer, state, mode) |
| **State mutations** | 2 locations | 3 locations |
| **Complexity** | Simpler - just position updates | More complex - DataView sync |
| **Side effects** | Minimal - just cursor/scroll | Significant - data structure changes |

## Winner: **Navigation Methods** 🏆

### Why Navigation is Better for Initial Trait Extraction:

1. **Simpler State Model**
   - Only updates positions (row, scroll)
   - No data structure modifications
   - No DataView cloning/syncing

2. **Fewer Dependencies**
   - No mode checking required
   - No DataView manipulation
   - Cleaner separation from data layer

3. **More Methods to Extract**
   - 9 navigation methods vs 4 column methods
   - Better demonstrates the pattern
   - More comprehensive trait

4. **Minimal Side Effects**
   - Just updates cursor position
   - No structural changes to data
   - Easier to test in isolation

5. **Clear Interface**
   - All methods follow exact same pattern
   - Single result type (RowNavigationResult)
   - Consistent behavior

## Proposed Navigation Trait Structure

```rust
// src/ui/traits/navigation.rs
pub trait NavigationBehavior {
    // Required methods that must be provided by implementor
    fn viewport_manager(&self) -> &RefCell<Option<ViewportManager>>;
    fn buffer_mut(&mut self) -> &mut dyn BufferAPI;
    fn state_container(&mut self) -> &mut AppStateContainer;
    fn get_row_count(&self) -> usize;
    
    // Helper that stays in trait
    fn apply_row_navigation_result(&mut self, result: RowNavigationResult) {
        self.buffer_mut().set_selected_row(Some(result.row_position));
        
        if result.viewport_changed {
            let mut offset = self.buffer().get_scroll_offset();
            offset.0 = result.row_scroll_offset;
            self.buffer_mut().set_scroll_offset(offset);
            self.state_container().navigation_mut().scroll_offset.0 = result.row_scroll_offset;
        }
        
        self.state_container().navigation_mut().selected_row = result.row_position;
    }
    
    // Provided navigation methods
    fn next_row(&mut self) {
        let nav_result = {
            let mut viewport_borrow = self.viewport_manager().borrow_mut();
            viewport_borrow.as_mut().map(|vm| vm.navigate_row_down())
        };
        
        if let Some(nav_result) = nav_result {
            self.apply_row_navigation_result(nav_result);
        }
    }
    
    fn previous_row(&mut self) { /* ... */ }
    fn goto_first_row(&mut self) { /* ... */ }
    fn goto_last_row(&mut self) { /* ... */ }
    fn page_up(&mut self) { /* ... */ }
    fn page_down(&mut self) { /* ... */ }
    // etc...
}
```

## Implementation Strategy

1. Create `src/ui/traits/mod.rs` and `src/ui/traits/navigation.rs`
2. Define `NavigationBehavior` trait with required methods
3. Move all navigation methods into trait as provided methods
4. Implement trait for `EnhancedTui`
5. Remove original methods from `EnhancedTui`
6. Test everything still works

This approach will prove the concept with minimal risk and maximum clarity.