Add editor search, syntax highlighting, git/CI integration, undo/redo, and UX overhaul#1
Merged
bluestreak01 merged 19 commits intomasterfrom Mar 22, 2026
Merged
Add editor search, syntax highlighting, git/CI integration, undo/redo, and UX overhaul#1bluestreak01 merged 19 commits intomasterfrom
bluestreak01 merged 19 commits intomasterfrom
Conversation
Expand tabs to spaces, strip control characters, and truncate lines to visible width in the viewer. Add buffer pre-fill and line padding to both viewer and hex viewer to prevent stale cell content from showing through. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Multi-file selection: - Shift+Up/Down to extend selection, Insert to toggle - Selected files highlighted in yellow bold - F5/F6/F8 operate on all selected files as a batch - Selection preserved across sort, cleared on directory change Dialogs redesigned to match Far Manager: - New dedicated Make Folder dialog with "Process multiple names" checkbox (semicolon-separated) and nested path support - All dialogs: outer margin, inner padding, dark teal focused input highlight, blinking cursor, Left/Right cursor navigation in input fields, Left/Right to swap buttons on button row - Copy/Move dialog: cursor navigation in destination field - Delete dialog: Yes/No buttons with keyboard navigation - Rename dialog: cursor-aware editing of file name - Theme colors for dialog input focus (dialog_input_fg_focused, dialog_input_bg) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Search (Ctrl+F in editor): - Search dialog with query input, direction toggle (forward/ backward), case-sensitive checkbox, Find/Cancel buttons - Forward and backward search with wrap-around - Match is highlighted via selection after finding - F3 / Ctrl+N for find-next, Shift+F3 / Ctrl+Shift+N for find-previous (reuses last search parameters) - Last search query persisted across dialog opens Dialog refactor: - Extract common rendering helpers into dialog_helpers.rs: render_dialog_frame, render_line, render_separator, render_checkbox, render_buttons, dialog_styles - All dialogs (delete, rename, mkdir, copy/move, search) now use shared helpers for consistent styling Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Performance: - Stream raw file bytes in 4MB chunks instead of per-line file opens - First-byte scan in find_bytes_sensitive/insensitive skips non-matching positions instead of checking every window - Forward search seeks directly to cursor byte offset via sparse index instead of reading from file start - Reverse search reads backwards in chunks from cursor, returns on first rfind hit — O(distance_to_match) not O(bytes_before_cursor) - Removed scan_to_end() from search — only scans enough to cover cursor Correctness: - Two-pass wrap-around: pass 0 searches from cursor in direction, pass 1 wraps. Cursor segment visited in both passes with proper skip_to/limit_to bounds - Reverse search uses selection anchor (match start) not cursor (match end) to avoid re-finding the same match - Line numbers in reverse computed via sparse index lookup (line_at_byte_offset) then converted to segment-relative, fixing off-by-one that only manifested in multi-chunk reads - Consistent vline_start + segment-relative return in both forward and reverse paths, correct for edited multi-segment files - match_char_len uses char count not byte length (UTF-8 safe) Key bindings: F7 opens search, Shift+F7 repeats in stored direction. Removed FindPrevious action — direction controlled by dialog toggle. Tests: 45 total, including 5 large-file tests (~6MB, 80K lines) that force multi-chunk behavior and verify line accuracy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Search cursor placement: - Cursor now placed at match START (like Far Manager), anchor at match END. Shift+arrow selects from the matched character. - search_selection flag ensures next Shift+arrow starts a fresh selection from cursor, not from the stale search anchor. - Forward skip uses anchor_col (match end), reverse limit uses cursor_col (match start) to avoid re-finding the same match. Dynamic line number width: - Line number column width computed from total line count instead of hardcoded 7. Fixes cursor/selection misalignment on files with 100K+ lines where line numbers exceed 5 digits. - Affects cursor positioning, visible_cols, and scroll calculations. Tests: 64 total including selection-after-search tests, CRLF tests, and large-file multi-chunk search tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Ctrl+Up/Down: go to top/bottom of file (works on all platforms) - Alt+PageUp/PageDown: same (Fn+Opt+Up/Down on Mac keyboards) - Ctrl+Home/End: unchanged (Linux keyboards with Home/End keys) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mouse support: - Left click positions cursor at clicked location - Handles tab expansion, control chars, scroll offset - Click on line number gutter ignored - Mouse scroll moves cursor 3 lines per tick Word navigation: - Ctrl+Left/Right on Linux, Option+Left/Right on Mac - Skips alphanumeric word boundaries and punctuation - Wraps across lines at line start/end Also: dynamic line_num_width stored on EditorState for accurate click-to-cursor coordinate conversion. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Unsaved changes dialog: - Shown when pressing Esc in editor with modifications - Three buttons: Save, Don't Save, Cancel - Consistent style with other dialogs (keyboard navigation) Mouse support in editor: - Left click positions cursor at clicked location - Handles tab expansion, control chars, scroll offset - Mouse scroll moves 3 lines per tick Word navigation: - Ctrl+Left/Right on Linux, Option+Left/Right (Alt+b/f) on Mac - Jumps by alphanumeric word boundaries Mac key bindings: - Alt+PageUp/PageDown (Fn+Opt+Up/Down) for top/bottom of file - Ctrl+Up/Down also works for top/bottom Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Syntax highlighting: - Tree-sitter integration for Rust, Java, Python, JavaScript/TS, JSON, Go, C, Bash, TOML - Hybrid approach: files <10MB get full parse cached on open (always accurate); files >=10MB use 200-line context window - Cached spans looked up via binary search (O(log n) per line) - Tab expansion maps all expanded spaces to same original char color (fixes tab color bleeding bug) - display_to_orig mapping built in single O(n) pass - Syntax colors defined in theme system (15 syn_* fields) - Cache invalidated on first edit (falls back to context window) Event handler cleanup: - Atomic stop flag + thread join before terminal restore - Fixes random escape sequence garbage printed on exit - Drop impl as safety net Also: removed Clone from AppMode (never cloned), fixed duplicate doc comment, fixed flaky test temp file names (atomic counter). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Editor cursor style (block, bar, underline, blinking variants) now defined in the theme system. Default set to BlinkingBar. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Git status in panels: - File status markers: ● modified, + added, - deleted, → renamed, ? untracked, ! conflict — colored per status - Branch display with ⎇ glyph in panel border title - Ahead/behind remote: ↑N ↓M with rev-list fallback when no tracking branch configured - Repo-wide status summary counts in title Architecture: - Shared GitCache across panels (same repo queried once) - 2-second TTL, invalidated on file operations - Single git call (status --branch --porcelain -unormal) - stderr suppressed to prevent TUI corruption - Path canonicalization for macOS symlink handling - Priority-based status aggregation for directories UI improvements: - Home dir shortened to ~ in panel title - Path truncated from left with ... when too long - Active panel title in white bold, inactive dimmed - Header bar simplified to margin (no duplicate path) - Panel border title is now the primary info display Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
State saved to ~/.config/middle-manager/state.json on quit: - Last search query, direction, case sensitivity - Panel paths (restored on next launch) - Sort field and direction per panel Fix: sort_ascending defaults to true (not false) so first launch sorts ascending. Manual Default impl + serde default_true for backwards compatibility with older state files. Removed unused copy dialog fields from state struct. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PR status display: - Shows PR #number with CI check status in panel title (✓ pass, ✗ fail, ○ pending) - F11 opens PR in browser - Uses gh CLI for GitHub API access Async architecture: - gh CLI spawned in background thread, never blocks UI - Results polled on 250ms tick, panel updates when ready - PR info preserved across git status refreshes (no flicker) - PR re-queried only on branch change, not every TTL refresh Correctness: - Uses gh pr view (not pr list --head) to find PR for current branch specifically, avoiding false matches from forks - Skips default branches (master/main/develop) — no wasted network calls - Graceful fallback: gh not installed or not authed → no PR shown Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Filesystem watcher: - notify crate with FSEvents (macOS) / inotify (Linux) - Zero syscalls when idle, instant detection of external changes - Watches both panel directories, re-watches on navigation - Replaced kqueue backend (leaked fds) with FSEvents default Bug fixes: - F10/Ctrl+Q in editor now shows unsaved changes dialog (previously bypassed it, risking data loss) - Cursor shape restored to terminal default on exit and panic (BlinkingBar was leaking into the user's shell) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI Panel (F2): - Tree view: checks shown collapsed, Enter expands to show steps inline with indentation, Enter again collapses - Enter on a step downloads log and opens in editor - Failed checks sorted to top, status markers (✓ ✗ ○ –) - Expand/collapse arrows (▶ ▼) on checks Azure DevOps support: - Timeline API for fetching job steps - Direct per-step log download via curl - Auto-detects Azure URLs from GitHub check rollup GitHub Actions support: - Zip log download via gh CLI, extracts largest job log - Falls back gracefully when step-level logs unavailable Async operations: - Check fetching with braille spinner (⠋⠙⠹⠸...) - Log download with progress display (file size polling) - Editor opens automatically when download completes Per-panel CI: - Each panel can have its own CI panel independently - Tab cycles: left → left_CI → right → right_CI → left - CI panel stays pinned to the panel it was opened from - Focus system: active panel has bright border, inactive dimmed - CI highlight only shown when focused UX: - Logs saved to current directory with sanitized filename - Footer changes contextually (normal vs CI mode) - F2 label in footer, consistent key/label styling - Empty StatusContext entries filtered out - Error messages shown in panel content, not duplicated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Quit dialog:
- F10 always shows Quit/Cancel confirmation dialog
- Tab/Left/Right switches between buttons, Enter confirms, Esc cancels
- Works from any panel/mode
- Esc in normal mode no longer exits
CI panel improvements:
- PR number shown in title (CI PR #6800)
- Auto-closes when navigating away from the repo/branch
- Left/Right tree navigation (expand/collapse/jump to parent)
- Mouse click to focus and select items in CI tree
- Mouse click on file panels works when CI is focused
- Prevents closing during active download
- Async step loading with spinner text ("⠙ loading...")
- GitHub Actions: per-job log API (no more full-run zip download)
Cleanup:
- Removed all dead code (ci_provider, find_step_log, download_run_logs, etc)
- Removed unused total_bytes field
- stdout flush on exit (fixes zsh arrow key corruption)
- Footer shows F2CI label
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comprehensive documentation of all features added in the vi_try2 branch: multi-file selection, git integration, CI panel, syntax highlighting, editor search, persistent state, filesystem watcher, Mac key bindings, and all dialog improvements. Updated key bindings tables, architecture section, and roadmap. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Undo/redo (Ctrl+Z / Ctrl+Shift+Z): - Operation-based, not snapshot-based: stores minimal deltas (Insert/Delete/SplitLine/JoinLine/DeleteLine/ClearLine) - ~20 bytes per entry vs ~200KB for snapshot approach - Inverse operations: Insert↔Delete, SplitLine↔JoinLine - Consecutive typing grouped into single undo entry - Groups break on whitespace for word-level undo - Redo stack cleared on new edits - 10,000 entry cap on undo stack - Cursor position restored on undo/redo All editing operations covered: - Insert character, delete backward/forward - Line joins (backspace at line start, delete at line end) - Insert newline (Enter), delete line (Ctrl+K/Ctrl+Y) 20 tests including edge cases: - Empty stack undo/redo (no panic) - Single-line file delete/undo - Full undo-all → redo-all cycles - Cursor position preservation - Whitespace group breaking - No-op operations don't push to stack Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Major feature release that transforms Middle Manager from a basic file manager into a developer-focused tool with deep git, GitHub, and CI integration.
Editor
File Panels
CI Panel (F2)
Dialog System
Infrastructure
Stats
Test plan
🤖 Generated with Claude Code