Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 184 additions & 0 deletions sql-cli/docs/analysis/CURRENT_STATE_ANALYSIS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Current State Analysis: Mapping the Chaos

## Executive Summary

Our TUI has **complex nested state** that's currently scattered across multiple components. Before designing the centralized state manager, we need to precisely map:
- All modes and substates
- Where state currently lives
- State transition triggers
- Side effects that need coordination

## Primary Mode Hierarchy

### 1. **INPUT MODE** (Command/Query entry)
**Primary State**: User typing SQL queries
```
AppMode::Command
├── Normal typing
├── Tab completion active
├── History search (Ctrl+R)
└── Cursor positioning
```

**Current State Locations**:
- `Buffer.mode` - Primary mode flag
- `Buffer.input_text` - Query text
- `Buffer.cursor_pos` - Cursor position
- `CompletionState` - Tab completion
- `HistorySearchState` - History search

### 2. **RESULTS MODE** (Navigation & Operations)
**Primary State**: User navigating/operating on query results
```
AppMode::Results
├── Normal navigation (hjkl, arrows)
├── Search substates:
│ ├── VIM search (/ key) - text search in data
│ ├── Column search (search key) - column name search
│ └── Fuzzy filter - live data filtering
├── Operations:
│ ├── Column operations (pin, hide, sort)
│ ├── Selection mode
│ └── Edit mode (future)
└── View states:
├── Normal view
├── Debug view (F5)
└── Pretty query view
```

**Current State Locations**:
- `Buffer.mode` - Primary mode
- `VimSearchManager` - Vim search state
- `ColumnSearchState` - Column search
- `FilterState` - Fuzzy filtering
- `NavigationState` - Cursor/viewport position
- `SortState` - Column sorting
- `SelectionState` - Row/cell selection

## State Transition Triggers

### Entering Results Mode
```
Trigger: User presses Enter on query
Effects needed:
├── Execute query → dataview
├── Switch to Results mode
├── Clear all search states
├── Reset viewport to (0,0)
├── Update status line
└── Set navigation context
```

### Search Mode Transitions
```
Trigger: User presses '/' (vim search)
Effects needed:
├── Enter VimSearch::Typing state
├── Show search input in status
├── Capture keystrokes for pattern
└── Clear other search states

Trigger: User presses Escape in search
Effects needed:
├── Exit search state
├── Restore normal navigation
├── Update key mapping context
├── Clear search display
└── Reset status line
```

### Mode Restoration
```
Trigger: User runs new query while in search
Effects needed:
├── Clear ALL search states
├── Reset to normal Results mode
├── Update viewport
├── Restore navigation keys
└── Update status line
```

## Current State Scatter Points

### 1. **Search State** (The 'N' key bug source)
```rust
// Scattered across 3+ locations:
buffer.get_search_pattern() // Regular search
vim_search_manager.is_active() // Vim search
state_container.column_search().is_active // Column search
// Plus fuzzy filter, history search...
```

### 2. **Navigation Context**
```rust
// Scattered across:
buffer.get_mode() // Primary mode
navigation_state.selected_row/column // Position
viewport_manager.viewport_position // Scroll state
selection_state.mode // Selection type
```

### 3. **UI Coordination**
```rust
// Status line needs:
mode + search_state + navigation + results + help_text

// Key mapping needs:
mode + search_active + has_results + selection_mode

// Viewport needs:
navigation_state + search_matches + selection
```

## Side Effects That Need Coordination

### When Exiting Search Mode
1. **Key Mapping**: 'N' should map to toggle_line_numbers, not search navigation
2. **Status Line**: Remove search pattern display, show normal mode info
3. **Viewport**: May need to restore previous position
4. **Input State**: Clear search input buffers

### When Entering Results Mode
1. **Navigation**: Initialize cursor position
2. **Viewport**: Set to show results from top
3. **Search States**: Clear all previous search state
4. **Key Context**: Enable results navigation keys
5. **Status**: Show results info (row count, etc.)

### When Switching Between Search Types
1. **Previous Search**: Clear state from previous search type
2. **Key Mapping**: Update context for new search type
3. **Status Display**: Show appropriate search UI
4. **Input Capture**: Redirect keystrokes appropriately

## The Core Problem

**Multiple sources of truth** lead to **inconsistent state**:
- Action system checks 3+ search state sources
- Key mapping depends on scattered boolean flags
- UI components each manage their own state
- State transitions don't automatically coordinate side effects

## Requirements for State Manager

### Must Handle
1. **Hierarchical States**: Mode → Submode → Operation state
2. **Automatic Side Effects**: Status line, viewport, key context updates
3. **State Validation**: Prevent impossible state combinations
4. **Transition Safety**: Ensure clean exits from all substates
5. **Debugging**: Central logging of all state changes

### Must Avoid
1. **Big Bang Migration**: Change everything at once
2. **Over-Engineering**: Complex state machines for simple cases
3. **Performance Issues**: State checks are in hot paths
4. **Breaking Changes**: Maintain current TUI behavior during migration

## Next Steps

1. **Design Precise State Model**: Define enum hierarchy for all states
2. **Identify Transition Points**: Map all places that trigger state changes
3. **Plan Migration Order**: Start with search state (highest pain point)
4. **Build Incrementally**: One state type at a time, maintain compatibility

This analysis shows why the 'N' key bug exists - we have at least 3 different "search active" states that aren't coordinated!
193 changes: 193 additions & 0 deletions sql-cli/docs/analysis/STATE_TRANSITION_MAPPING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# State Transition Mapping: The Current Chaos

## Overview

Found **57 set_mode() calls** and **15+ search state operations** scattered across the codebase. This documents the current transition triggers and their required side effects.

## Mode Transition Triggers (57 locations!)

### 1. **Command → Results** (Query Execution)
**Trigger Locations**:
- `ui/enhanced_tui.rs:2251` - Execute query from command mode
- `ui/enhanced_tui.rs:2914` - Resume from results
- `ui/enhanced_tui.rs:2986` - Various result transitions
- `action_handler.rs:65` - Action system result mode
- Multiple other locations...

**Required Side Effects**:
```rust
// CURRENT: Scattered manual coordination
self.buffer_mut().set_mode(AppMode::Results);
// Missing: Clear search states, reset viewport, update status

// NEEDED: Coordinated transition
state_manager.transition(StateTransition::ExecuteQuery {
query: query_text
});
// Should automatically:
// - Clear all search states (vim, column, fuzzy)
// - Reset viewport to (0,0)
// - Update key mapping context
// - Reset status line to results mode
// - Initialize navigation state
```

### 2. **Results → Command** (Back to Input)
**Trigger Locations**:
- `ui/enhanced_tui.rs:463,771` - Escape key handlers
- `action_handler.rs:60,69,99` - Action system
- Multiple exit paths...

**Required Side Effects**:
```rust
// CURRENT: Only mode change
self.buffer_mut().set_mode(AppMode::Command);

// NEEDED: Full restoration
state_manager.transition(StateTransition::ReturnToCommand);
// Should restore:
// - Previous query text in input
// - Cursor position in input
// - Clear all results-mode state
// - Update status line
```

### 3. **Search Mode Entries** (Multiple Types)
**Trigger Locations**:
- `ui/enhanced_tui.rs:2706,3000,3019` - Column search entries
- `action_handler.rs:202` - General search
- `vim_search_manager.rs:45` - Vim search start

**Current Problems**:
```rust
// SCATTERED: Each search type managed separately
buffer.set_mode(AppMode::ColumnSearch); // Column search
vim_search_manager.start_search(); // Vim search
state_container.start_search(pattern); // Regular search

// CONFLICTS: Multiple search states can be active!
// RESULT: 'N' key bug - system doesn't know which search is active
```

## Search State Transition Chaos

### Current Search State Locations
```rust
// 1. VimSearchManager - /search functionality
enum VimSearchState {
Inactive,
Typing { pattern: String },
Navigating { matches, current_index },
}

// 2. ColumnSearchState - Column name search
struct ColumnSearchState {
is_active: bool,
pattern: String,
matching_columns: Vec<(usize, String)>,
}

// 3. Regular SearchState - Data search
struct SearchState {
is_active: bool,
pattern: String,
matches: Vec<SearchMatch>,
}

// 4. FilterState - Fuzzy filtering
struct FilterState {
is_active: bool,
pattern: String,
// ... filter logic
}

// PROBLEM: All can be active simultaneously!
```

### Search Transition Problems
```rust
// TRIGGER: User presses '/' for vim search
vim_search_manager.start_search();
// MISSING: Clear other search states!

// TRIGGER: User presses Escape
vim_search_manager.cancel_search();
// MISSING: Update action context, key mappings, status line

// TRIGGER: Execute new query
self.state_container.clear_search();
self.state_container.clear_column_search();
self.vim_search_manager.borrow_mut().cancel_search();
// FRAGILE: Manual coordination, easy to miss one
```

## Required State Coordination Matrix

| Transition | Buffer Mode | Search States | Viewport | Keys | Status |
|-----------|-------------|---------------|----------|------|--------|
| Execute Query | → Results | Clear ALL | Reset (0,0) | Navigation | Results info |
| Enter Vim Search | Same | Clear others → Vim | Preserve | Search nav | Search UI |
| Exit Search | Same | Clear current | Restore | Restore nav | Normal mode |
| Return to Command | → Command | Clear ALL | N/A | Input keys | Command UI |
| Switch Search Type | Same | Clear old → New | Adjust | New search | New search UI |

## Critical Coordination Points

### 1. **Search State Conflicts** (The 'N' key bug)
```rust
// CURRENT PROBLEM: Action context checks all sources
has_search: !buffer.get_search_pattern().is_empty()
|| self.vim_search_manager.borrow().is_active()
|| self.state_container.column_search().is_active

// SOLUTION NEEDED: Single source of truth
app_state.current_search_type() -> Option<SearchType>
```

### 2. **Mode Transition Side Effects**
```rust
// CURRENT: Manual, inconsistent
set_mode(AppMode::Results);
// Sometimes clears search, sometimes doesn't
// Sometimes updates viewport, sometimes doesn't

// NEEDED: Automatic side effects
state_manager.transition(EnterResultsMode);
// Always clears search, always resets viewport, always updates UI
```

### 3. **Key Mapping Context**
```rust
// CURRENT: Complex boolean logic in action context
ActionContext {
has_search: /* 3-way check */,
mode: /* buffer mode */,
has_results: /* buffer check */,
// ... more scattered flags
}

// NEEDED: Derived from central state
ActionContext::from_app_state(&state_manager.current_state())
```

## Implementation Strategy

### Phase 1: Search State Unification
1. Create `enum SearchType { None, Vim, Column, Data, Fuzzy }`
2. Single `current_search: SearchType` in state manager
3. Replace all search state checks with single source
4. **Fix 'N' key bug immediately**

### Phase 2: Mode Transition Coordination
1. Replace direct `set_mode()` calls with state transitions
2. Implement automatic side effects for each transition
3. Add state validation (prevent impossible combinations)

### Phase 3: Full State Centralization
1. Move all navigation, selection, filter state to manager
2. Implement complete state history and debugging
3. Remove all scattered state management

## Next Step: Start Small

Begin with **search state unification** - it's the highest pain point and most isolated. The 'N' key bug fix will validate the approach before expanding to full mode management.
Loading
Loading