tick system, AVX2 UTF-8 decoder, uh faster in general
This commit is contained in:
+346
@@ -0,0 +1,346 @@
|
||||
# Main.rs Reorganization Plan
|
||||
|
||||
This document identifies sections of `src/main.rs` (2793 lines) that could be extracted into separate modules to improve code organization, maintainability, and testability.
|
||||
|
||||
## Summary of Proposed Extractions
|
||||
|
||||
| Module Name | Lines | Primary Contents |
|
||||
|-------------|-------|------------------|
|
||||
| `pty_buffer.rs` | ~180 | `SharedPtyBuffer`, `BufferState` |
|
||||
| `pane.rs` | ~400 | `PaneId`, `Pane`, `PaneGeometry`, `SplitNode` |
|
||||
| `tab.rs` | ~150 | `TabId`, `Tab` |
|
||||
| `selection.rs` | ~45 | `CellPosition`, `Selection` |
|
||||
| `statusline.rs` | ~220 | `GitStatus`, `build_cwd_section()`, `build_git_section()`, `get_git_status()` |
|
||||
| `instance.rs` | ~45 | PID file management, `signal_existing_instance()` |
|
||||
|
||||
---
|
||||
|
||||
## 1. PTY Buffer Module (`pty_buffer.rs`)
|
||||
|
||||
**Lines: 30-227 (~197 lines)**
|
||||
|
||||
### Contents
|
||||
- `PTY_BUF_SIZE` constant
|
||||
- `SharedPtyBuffer` struct and impl
|
||||
- `BufferState` struct
|
||||
- `unsafe impl Sync/Send for SharedPtyBuffer`
|
||||
|
||||
### Description
|
||||
This is a self-contained, zero-copy PTY I/O buffer implementation inspired by Kitty. It has no dependencies on other application-specific types and is purely concerned with efficient I/O buffering between an I/O thread and the main thread.
|
||||
|
||||
### Types/Functions to Extract
|
||||
```rust
|
||||
const PTY_BUF_SIZE: usize
|
||||
struct BufferState
|
||||
struct SharedPtyBuffer
|
||||
impl SharedPtyBuffer
|
||||
impl Drop for SharedPtyBuffer
|
||||
unsafe impl Sync for SharedPtyBuffer
|
||||
unsafe impl Send for SharedPtyBuffer
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
- `std::cell::UnsafeCell`
|
||||
- `std::sync::Mutex`
|
||||
- `libc` (for `eventfd`, `read`, `write`, `close`)
|
||||
|
||||
### Challenges
|
||||
- **Unsafe code**: Contains `UnsafeCell` and raw pointer manipulation. Must carefully preserve safety invariants.
|
||||
- **libc dependency**: Uses Linux-specific `eventfd` syscalls.
|
||||
|
||||
### Recommendation
|
||||
**High priority extraction.** This is a well-documented, self-contained component with clear boundaries. Would benefit from its own unit tests for buffer operations.
|
||||
|
||||
---
|
||||
|
||||
## 2. Pane Module (`pane.rs`)
|
||||
|
||||
**Lines: 229-691 (~462 lines)**
|
||||
|
||||
### Contents
|
||||
- `PaneId` - unique identifier with atomic generation
|
||||
- `Pane` - terminal + PTY + selection state
|
||||
- `PaneGeometry` - pixel layout information
|
||||
- `SplitNode` - tree structure for split pane layouts
|
||||
|
||||
### Types/Functions to Extract
|
||||
```rust
|
||||
struct PaneId
|
||||
impl PaneId
|
||||
|
||||
struct Pane
|
||||
impl Pane
|
||||
- new()
|
||||
- resize()
|
||||
- write_to_pty()
|
||||
- child_exited()
|
||||
- foreground_matches()
|
||||
- calculate_dim_factor()
|
||||
|
||||
struct PaneGeometry
|
||||
|
||||
enum SplitNode
|
||||
impl SplitNode
|
||||
- leaf()
|
||||
- split()
|
||||
- layout()
|
||||
- find_geometry()
|
||||
- collect_geometries()
|
||||
- find_neighbor()
|
||||
- overlaps_horizontally()
|
||||
- overlaps_vertically()
|
||||
- remove_pane()
|
||||
- contains_pane()
|
||||
- split_pane()
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
- `zterm::terminal::{Direction, Terminal, TerminalCommand, MouseTrackingMode}`
|
||||
- `zterm::pty::Pty`
|
||||
- `std::sync::Arc`
|
||||
- `std::os::fd::AsRawFd`
|
||||
- `SharedPtyBuffer` (from pty_buffer module)
|
||||
- `Selection` (from selection module)
|
||||
|
||||
### Challenges
|
||||
- **Cross-module dependencies**: `Pane` references `SharedPtyBuffer` and `Selection`, so those would need to be extracted first or extracted together.
|
||||
- **`SplitNode` complexity**: The recursive tree structure has complex layout logic. Consider keeping `SplitNode` with `Pane` since they're tightly coupled.
|
||||
|
||||
### Recommendation
|
||||
**High priority extraction.** The pane management is a distinct concern from the main application loop. This would make the split tree logic easier to test in isolation.
|
||||
|
||||
---
|
||||
|
||||
## 3. Tab Module (`tab.rs`)
|
||||
|
||||
**Lines: 693-872 (~180 lines)**
|
||||
|
||||
### Contents
|
||||
- `TabId` - unique identifier with atomic generation
|
||||
- `Tab` - collection of panes with a split tree
|
||||
|
||||
### Types/Functions to Extract
|
||||
```rust
|
||||
struct TabId
|
||||
impl TabId
|
||||
|
||||
struct Tab
|
||||
impl Tab
|
||||
- new()
|
||||
- active_pane() / active_pane_mut()
|
||||
- resize()
|
||||
- write_to_pty()
|
||||
- check_exited_panes()
|
||||
- split()
|
||||
- remove_pane()
|
||||
- close_active_pane()
|
||||
- focus_neighbor()
|
||||
- get_pane() / get_pane_mut()
|
||||
- collect_pane_geometries()
|
||||
- child_exited()
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
- `std::collections::HashMap`
|
||||
- `PaneId`, `Pane`, `PaneGeometry`, `SplitNode` (from pane module)
|
||||
- `zterm::terminal::Direction`
|
||||
|
||||
### Challenges
|
||||
- **Tight coupling with Pane module**: Tab is essentially a container for panes. Consider combining into a single `pane.rs` module or using `pane/mod.rs` with submodules.
|
||||
|
||||
### Recommendation
|
||||
**Medium priority.** Could be combined with the pane module under `pane/mod.rs` with `pane/tab.rs` as a submodule, or kept as a separate `tab.rs`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Selection Module (`selection.rs`)
|
||||
|
||||
**Lines: 1218-1259 (~42 lines)**
|
||||
|
||||
### Contents
|
||||
- `CellPosition` - column/row position
|
||||
- `Selection` - start/end positions for text selection
|
||||
|
||||
### Types/Functions to Extract
|
||||
```rust
|
||||
struct CellPosition
|
||||
struct Selection
|
||||
impl Selection
|
||||
- normalized()
|
||||
- to_screen_coords()
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
- None (completely self-contained)
|
||||
|
||||
### Challenges
|
||||
- **Very small**: Only 42 lines. May be too small to justify its own file.
|
||||
|
||||
### Recommendation
|
||||
**Low priority as standalone.** Consider bundling with the pane module since selection is per-pane state, or creating a `types.rs` for small shared types.
|
||||
|
||||
---
|
||||
|
||||
## 5. Statusline Module (`statusline.rs`)
|
||||
|
||||
**Lines: 917-1216 (~300 lines)**
|
||||
|
||||
### Contents
|
||||
- `build_cwd_section()` - creates CWD statusline section
|
||||
- `GitStatus` struct - git repository state
|
||||
- `get_git_status()` - queries git for repo status
|
||||
- `build_git_section()` - creates git statusline section
|
||||
|
||||
### Types/Functions to Extract
|
||||
```rust
|
||||
fn build_cwd_section(cwd: &str) -> StatuslineSection
|
||||
struct GitStatus
|
||||
fn get_git_status(cwd: &str) -> Option<GitStatus>
|
||||
fn build_git_section(cwd: &str) -> Option<StatuslineSection>
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
- `zterm::renderer::{StatuslineComponent, StatuslineSection}`
|
||||
- `std::process::Command` (for git commands)
|
||||
- `std::env` (for HOME variable)
|
||||
|
||||
### Challenges
|
||||
- **External process calls**: Uses `git` commands. Consider whether this should be async or cached.
|
||||
- **Powerline icons**: Uses hardcoded Unicode codepoints (Nerd Font icons).
|
||||
|
||||
### Recommendation
|
||||
**High priority extraction.** This is completely independent of the main application state. Would benefit from:
|
||||
- Caching git status (it's currently queried every frame)
|
||||
- Unit tests for path transformation logic
|
||||
- Potential async git queries
|
||||
|
||||
---
|
||||
|
||||
## 6. Instance Management Module (`instance.rs`)
|
||||
|
||||
**Lines: 874-915, 2780-2792 (~55 lines total)**
|
||||
|
||||
### Contents
|
||||
- PID file path management
|
||||
- Single-instance detection and signaling
|
||||
- Signal handler for SIGUSR1
|
||||
|
||||
### Types/Functions to Extract
|
||||
```rust
|
||||
fn pid_file_path() -> PathBuf
|
||||
fn signal_existing_instance() -> bool
|
||||
fn write_pid_file() -> std::io::Result<()>
|
||||
fn remove_pid_file()
|
||||
|
||||
// From end of file:
|
||||
static mut EVENT_PROXY: Option<EventLoopProxy<UserEvent>>
|
||||
extern "C" fn handle_sigusr1(_: i32)
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
- `std::fs`
|
||||
- `std::path::PathBuf`
|
||||
- `libc` (for `kill` syscall)
|
||||
- `winit::event_loop::EventLoopProxy`
|
||||
- `UserEvent` enum
|
||||
|
||||
### Challenges
|
||||
- **Global static**: The `EVENT_PROXY` static is `unsafe` and tightly coupled to the signal handler.
|
||||
- **Split location**: The signal handler is at the end of the file, separate from PID functions.
|
||||
|
||||
### Recommendation
|
||||
**Medium priority.** Small but distinct concern. The global static handling could be cleaner in a dedicated module.
|
||||
|
||||
---
|
||||
|
||||
## 7. Additional Observations
|
||||
|
||||
### UserEvent Enum (Line 1262-1270)
|
||||
```rust
|
||||
enum UserEvent {
|
||||
ShowWindow,
|
||||
PtyReadable(PaneId),
|
||||
ConfigReloaded,
|
||||
}
|
||||
```
|
||||
This is a small enum but is referenced throughout. Consider placing in a `types.rs` or `events.rs` module.
|
||||
|
||||
### Config Watcher (Lines 2674-2735)
|
||||
The `setup_config_watcher()` function is self-contained and could go in the instance module or a dedicated `config_watcher.rs`.
|
||||
|
||||
### App Struct (Lines 1272-1334)
|
||||
The `App` struct and its impl are the core of the application and should remain in `main.rs`. However, some of its methods could potentially be split:
|
||||
- I/O thread management (lines 1418-1553)
|
||||
- Keyboard/keybinding handling (lines 1773-2221)
|
||||
- Mouse handling (scattered through `window_event`)
|
||||
|
||||
### Keyboard Handling
|
||||
Lines 1773-2221 contain significant keyboard handling logic. This could potentially be extracted, but it's tightly integrated with the `App` state.
|
||||
|
||||
---
|
||||
|
||||
## Suggested Module Structure
|
||||
|
||||
```
|
||||
src/
|
||||
main.rs (~1200 lines - App, ApplicationHandler, main())
|
||||
lib.rs (existing)
|
||||
pty_buffer.rs (new - ~200 lines)
|
||||
pane.rs (new - ~500 lines, includes SplitNode)
|
||||
tab.rs (new - ~180 lines)
|
||||
selection.rs (new - ~45 lines, or merge with pane.rs)
|
||||
statusline.rs (new - ~300 lines)
|
||||
instance.rs (new - ~60 lines)
|
||||
config.rs (existing)
|
||||
...
|
||||
```
|
||||
|
||||
Alternative with submodules:
|
||||
```
|
||||
src/
|
||||
main.rs
|
||||
lib.rs
|
||||
pane/
|
||||
mod.rs (re-exports)
|
||||
pane.rs (Pane, PaneId)
|
||||
split.rs (SplitNode, PaneGeometry)
|
||||
selection.rs (Selection, CellPosition)
|
||||
tab.rs
|
||||
pty_buffer.rs
|
||||
statusline.rs
|
||||
instance.rs
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. **`pty_buffer.rs`** - No internal dependencies, completely self-contained
|
||||
2. **`selection.rs`** - No dependencies, simple extraction
|
||||
3. **`statusline.rs`** - No internal dependencies, high value for testability
|
||||
4. **`instance.rs`** - Small, isolated concern
|
||||
5. **`pane.rs`** - Depends on pty_buffer and selection
|
||||
6. **`tab.rs`** - Depends on pane
|
||||
|
||||
---
|
||||
|
||||
## Testing Opportunities
|
||||
|
||||
After extraction, these modules would benefit from unit tests:
|
||||
|
||||
| Module | Testable Functionality |
|
||||
|--------|----------------------|
|
||||
| `pty_buffer` | Buffer overflow handling, space checking, wakeup signaling |
|
||||
| `selection` | `normalized()` ordering, `to_screen_coords()` boundary conditions |
|
||||
| `statusline` | Path normalization (~/ replacement), git status parsing |
|
||||
| `pane` / `SplitNode` | Layout calculations, neighbor finding, tree operations |
|
||||
| `instance` | PID file creation/cleanup (integration test) |
|
||||
|
||||
---
|
||||
|
||||
## Notes on Maintaining Backward Compatibility
|
||||
|
||||
All extracted types should be re-exported from `lib.rs` or a prelude if they're used externally. The current architecture appears to be internal to the binary, so this is likely not a concern.
|
||||
|
||||
The `Pane` and `Tab` types are not part of the public API (defined in `main.rs`), so extraction won't affect external consumers.
|
||||
Reference in New Issue
Block a user