10 KiB
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_SIZEconstantSharedPtyBufferstruct and implBufferStatestructunsafe 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
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::UnsafeCellstd::sync::Mutexlibc(foreventfd,read,write,close)
Challenges
- Unsafe code: Contains
UnsafeCelland raw pointer manipulation. Must carefully preserve safety invariants. - libc dependency: Uses Linux-specific
eventfdsyscalls.
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 generationPane- terminal + PTY + selection statePaneGeometry- pixel layout informationSplitNode- tree structure for split pane layouts
Types/Functions to Extract
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::Ptystd::sync::Arcstd::os::fd::AsRawFdSharedPtyBuffer(from pty_buffer module)Selection(from selection module)
Challenges
- Cross-module dependencies:
PanereferencesSharedPtyBufferandSelection, so those would need to be extracted first or extracted together. SplitNodecomplexity: The recursive tree structure has complex layout logic. Consider keepingSplitNodewithPanesince 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 generationTab- collection of panes with a split tree
Types/Functions to Extract
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::HashMapPaneId,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.rsmodule or usingpane/mod.rswith 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 positionSelection- start/end positions for text selection
Types/Functions to Extract
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 sectionGitStatusstruct - git repository stateget_git_status()- queries git for repo statusbuild_git_section()- creates git statusline section
Types/Functions to Extract
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
gitcommands. 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
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::fsstd::path::PathBuflibc(forkillsyscall)winit::event_loop::EventLoopProxyUserEventenum
Challenges
- Global static: The
EVENT_PROXYstatic isunsafeand 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)
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
pty_buffer.rs- No internal dependencies, completely self-containedselection.rs- No dependencies, simple extractionstatusline.rs- No internal dependencies, high value for testabilityinstance.rs- Small, isolated concernpane.rs- Depends on pty_buffer and selectiontab.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.