PROJECT OVERVIEW:
The goal is to create a single-page web application (SPA) that serves as a modern, terminal-inspired code editor, drawing heavy inspiration from the features and philosophy of Helix and Kakoune. This application aims to provide a powerful, modal editing experience with advanced features like multiple cursors, Tree-sitter integration for robust syntax analysis, and seamless Language Server Protocol (LSP) support for IDE-like functionalities. The key value proposition is to offer a highly efficient, configurable, and accessible code editing environment that can be used directly in the browser, over SSH, or within terminal multiplexers like tmux, without the overhead of Electron or extensive JavaScript dependencies. The target audience includes developers who prefer modal editing, value performance, and seek a consistent editing experience across different environments.
TECH STACK:
- Frontend Framework: React (using Vite for fast development server and build)
- Styling: Tailwind CSS for rapid UI development and utility-first styling.
- State Management: Zustand for efficient and simple global state management.
- Code Editor Component: Utilize a performant, customizable text area or a dedicated web-based code editor library (e.g., CodeMirror 6 with custom modes or Monaco Editor if complexity allows, though aiming for a lighter solution initially might be better).
- Syntax Highlighting: Integrate Tree-sitter parsing capabilities (potentially via WASM bindings or a Rust backend compiled to WASM) to enable robust, error-tolerant syntax highlighting and AST generation.
- LSP Client: Implement a WebSocket-based LSP client to communicate with language servers.
- Routing: React Router DOM for potential future expansion to multiple views, though starting as a true SPA with a single main editor view.
- Icons: Heroicons orlucide-react for clean SVG icons.
- Animations: Framer Motion for subtle and meaningful UI animations and transitions.
CORE FEATURES:
1. **Modal Editing Experience (Inspired by Kakoune/Helix):**
* **User Flow:** Users interact with the editor in two primary modes: Normal Mode (for navigation and commands) and Insert Mode (for text input). Switching between modes is typically done via the 'Esc' key or other predefined keybindings.
* **Selection-Based Editing:** Commands operate on selections (ranges of text). When a command is invoked, it acts upon all active selections. This allows for powerful, concurrent editing operations. For example, selecting multiple lines and then invoking a delete command removes all selected lines simultaneously.
* **Keybindings:** Define a clear set of keybindings for navigation (h, j, k, l, w, b, e, etc.), text manipulation (d, c, y, p), selection expansion (v, V, Ctrl+V), and mode switching.
2. **Multiple Cursors/Selections:**
* **User Flow:** Users can create multiple, independent cursors. This can be achieved through specific keybindings (e.g., Ctrl+N to add next occurrence, Ctrl+P to add previous, or Cmd/Ctrl+Click). Editing actions (typing, deleting, pasting) are applied to all cursors simultaneously.
* **Implementation:** The editor component must support managing multiple selection ranges and cursor positions efficiently. Actions update all selections in parallel.
3. **Tree-sitter Integration:**
* **User Flow:** As the user types, Tree-sitter continuously parses the code in the background, generating an Abstract Syntax Tree (AST). This AST is used for accurate syntax highlighting, intelligent code navigation (jumping to definitions, finding usages), and potentially code formatting/refactoring.
* **Implementation:** Requires compiling Tree-sitter parsers for supported languages to WASM. The frontend application will load these WASM modules and use them to parse code chunks. Error tolerance is key, ensuring highlighting remains functional even with syntax errors.
4. **Language Server Protocol (LSP) Support:**
* **User Flow:** The application automatically detects the language of the open file and attempts to connect to a corresponding language server (running either in a backend service or potentially WASM-compiled servers). Features like autocompletion popups, "Go to Definition" (triggered by a keybinding), inline error diagnostics, and hover-over documentation become available.
* **Implementation:** Implement a WebSocket client to communicate with the LSP. Manage server connections, request/response handling, and integrate LSP features into the UI (e.g., completion dropdowns, diagnostic squiggles).
5. **Fuzzy Finder (Files & Symbols):**
* **User Flow:** Triggered by a keybinding (e.g., Ctrl+P for files, Ctrl+Shift+P for symbols). A modal overlay appears, allowing users to type fuzzy queries to quickly find and open files or navigate to symbols (functions, classes) within the project.
* **Implementation:** Requires indexing project files/symbols. Use a fuzzy searching algorithm (like Fuse.js or a custom implementation) to provide fast, relevant results as the user types.
6. **Basic Theming and Configuration:**
* **User Flow:** Users can switch between predefined themes (e.g., 'Dracula', 'Solarized Light', 'Monokai') via a settings menu or command. Basic configuration options (font size, tab size) should be adjustable.
* **Implementation:** Theme switching involves changing CSS variables or Tailwind's configuration dynamically. Store user preferences in `localStorage`.
UI/UX DESIGN:
- **Layout:** A clean, minimalist, single-page layout. The primary focus is the editor pane. A subtle status bar at the bottom displays mode, file path, diagnostics, and other relevant info. A collapsible sidebar could be added for file navigation in future iterations, but MVP is focused on the editor.
- **Color Palette:** Primarily dark themes with high contrast for code readability. Accent colors for selections, cursors, and diagnostics should be distinct but not distracting. Example: Base dark background (#1E1E1E), text (#D4D4D4), selection/cursor highlights (#5F87AF), accent for errors (red), warnings (yellow).
- **Typography:** A monospaced font (e.g., 'Fira Code', 'JetBrains Mono', 'Cascadia Code') with ligatures enabled for code. Font size should be adjustable.
- **Responsive Design:** While primarily desktop-focused, the UI should adapt gracefully to different screen sizes. Ensure usability on smaller screens, perhaps by simplifying the UI or requiring horizontal scrolling.
- **Modals:** Overlays for fuzzy finder, settings, and potentially command palettes should be centered, have a subtle backdrop blur, and animate smoothly.
COMPONENT BREAKDOWN:
- `App.jsx`: Main application component, sets up routing (if any), global context/state providers.
- `EditorPane.jsx`: The core component containing the text area/editor library. Manages editor state, keybindings, and interactions.
* `props`: `initialValue` (string), `language` (string), `themeConfig` (object), `lspEnabled` (boolean)
- `StatusBar.jsx`: Displays editor status (mode, filename, line/col, diagnostics).
* `props`: `currentMode` (string), `filePath` (string), `diagnostics` (array)
- `FuzzyFinder.jsx`: Modal component for file/symbol search.
* `props`: `isOpen` (boolean), `onClose` (function), `searchType` (string: 'files' | 'symbols'), `projectFiles` (array)
- `CompletionWidget.jsx`: Renders the LSP autocompletion dropdown.
* `props`: `items` (array), `onSelectItem` (function), `position` (object)
- `SettingsModal.jsx`: Modal for user preferences.
* `props`: `isOpen` (boolean), `onClose` (function), `config` (object), `onUpdateConfig` (function)
- `KeybindingManager.js`: (Utility/Service) Handles global key event listeners and maps them to editor actions based on the current mode.
- `LspClient.js`: (Service) Manages WebSocket connection to the LSP server and handles message passing.
- `TreeSitterParser.js`: (Service) WASM wrapper for Tree-sitter parsing and AST generation.
DATA MODEL:
- **Editor State (`Zustand` store):**
```javascript
{
code: string, // Current content of the editor
language: string, // e.g., 'javascript', 'rust', 'python'
mode: 'normal' | 'insert' | 'visual', // Current editor mode
selections: Array<{ start: { row: number, column: number }, end: { row: number, column: number } }>,
cursors: Array<{ row: number, column: number }>,
theme: string, // e.g., 'dracula', 'solarized-light'
fontSize: number,
lspStatus: 'disconnected' | 'connecting' | 'connected' | 'error',
diagnostics: Array<{ range: { start: { row: number, column: number }, end: { row: number, column: number } }, severity: number, message: string, code?: string }>,
// Other settings like tabSize, etc.
}
```
- **Mock Data Formats:**
* `CompletionItem`: `{ label: string, kind: number, detail?: string, documentation?: string }`
* `Diagnostic`: `{ range: { start: { row, column }, end: { row, column } }, severity: 1 | 2 | 3 | 4, message: string, source?: string, code?: string }`
* `SymbolInformation`: `{ name: string, kind: number, location: { uri: string, range: { start: { row, column }, end: { row, column } } } }`
ANIMATIONS & INTERACTIONS:
- **Mode Switching:** Subtle fade or scale animation when switching between Normal, Insert, and Visual modes.
- **Fuzzy Finder:** Smooth slide-in/slide-out animation for the modal. Highlighted search results animate slightly on hover.
- **Completions:** Fade-in animation for the completion widget. Smooth scrolling within the widget.
- **Diagnostics:** Squiggle underlines for errors/warnings rendered with a slight fade-in. Tooltips for diagnostics should appear smoothly on hover.
- **Loading States:** Use subtle spinners or skeleton loaders when performing operations like fetching symbols, connecting to LSP, or parsing large files.
- **Hover Effects:** Minimalist hover effects on status bar items or buttons.
EDGE CASES:
- **Empty State:** Handle initial editor load with no content gracefully. Provide placeholders or hints.
- **Error Handling:** Gracefully handle LSP connection errors, Tree-sitter parsing failures, and invalid user input. Display user-friendly error messages.
- **Validation:** Implement input validation for settings and any form-based inputs.
- **Accessibility (a11y):** Ensure proper ARIA attributes, keyboard navigability for all interactive elements (including modals and menus), and sufficient color contrast.
- **Large Files:** Implement strategies for handling very large files (virtual rendering, debounced parsing) to maintain performance.
- **Disconnection:** Gracefully handle WebSocket disconnections from the LSP server, inform the user, and attempt reconnection.
SAMPLE DATA:
1. **Initial Code (JavaScript):**
```javascript
function greet(name) {
console.log(`Hello, ${name}!`);
}
greet('World');
```
2. **Editor State:**
```json
{
"code": "function greet(name) {\n console.log(`Hello, ${name}!`);\n}\n\ngreet('World');",
"language": "javascript",
"mode": "normal",
"selections": [],
"cursors": [{"row": 0, "column": 0}],
"theme": "dracula",
"fontSize": 14,
"lspStatus": "connected",
"diagnostics": [
{
"range": {"start": {"row": 1, "column": 2}, "end": {"row": 1, "column": 12}},
"severity": 2, // Warning
"message": "Variable 'console' is possibly unused."
}
]
}
```
3. **Completion Items:**
```json
[
{"label": "function", "kind": 12},
{"label": "const", "kind": 12},
{"label": "let", "kind": 12},
{"label": "console", "kind": 7, "detail": "console object"}
]
```
4. **Diagnostic (Error):**
```json
{
"range": {"start": {"row": 3, "column": 0}, "end": {"row": 3, "column": 10}},
"severity": 1, // Error
"message": "Missing semicolon at the end of statement.",
"code": "TS1005"
}
```
5. **Symbol Information:**
```json
[
{"name": "greet", "kind": 12, "location": {"uri": "file:///path/to/file.js", "range": {"start": {"row": 0, "column": 9}, "end": {"row": 0, "column": 14}}}}
]
```
6. **File List for Fuzzy Finder:**
```json
[
"src/index.js",
"src/utils/helpers.js",
"tests/math.test.js",
"README.md",
"package.json"
]
```
7. **Theme Configuration ('dracula'):**
```json
{
"name": "dracula",
"colors": {
"editor.background": "#282A36",
"editor.foreground": "#F8F8F2",
"selection.background": "#44475A",
"cursor.foreground": "#F8F8F2",
"syntax.keyword": "#FF79C6",
"syntax.string": "#F1FA8C",
"syntax.comment": "#6272A4"
}
}
```
DEPLOYMENT NOTES:
- **Build Tool:** Vite is recommended for its speed and ease of configuration. `vite build` will create optimized static assets.
- **Environment Variables:** Use `.env` files for configuration (e.g., `VITE_LSP_SERVER_URL`). Ensure sensitive information is not committed to the repository.
- **Performance Optimizations:** Code splitting (if the app grows), lazy loading components, memoization (React.memo), and efficient state updates are crucial. Tree-shaking by Vite will help reduce bundle size.
- **WASM Loading:** Ensure WASM modules for Tree-sitter are loaded efficiently, possibly using dynamic imports.
- **Static Hosting:** Deploy the build output to any static hosting provider (Netlify, Vercel, GitHub Pages, S3).
- **LSP Server Management:** Decide if the LSP server runs client-side (WASM) or server-side (requires a backend infrastructure, potentially more complex for a browser-only app, unless connecting to a remote server).
- **Caching:** Leverage browser caching for static assets. Consider service workers for offline capabilities in the future.
- **Error Reporting:** Integrate a client-side error reporting service (e.g., Sentry) to monitor production issues.