|
| 1 | +# Phase 4 Dual-Cursor Implementation Status |
| 2 | + |
| 3 | +## COMPLETED WORK ✅ |
| 4 | + |
| 5 | +### Phase 1: Script Detection (COMMITTED) |
| 6 | +- Commit: 97467f8 |
| 7 | +- File: `src/script-detection.ts` (NEW) |
| 8 | +- Features: |
| 9 | + - Unicode range detection for Arabic, Syriac, N'Ko |
| 10 | + - Context-aware detection for neutral characters |
| 11 | + - Excludes Arabic punctuation (comma, semicolon, etc.) |
| 12 | + - Spaces/whitespace always treated as word boundaries |
| 13 | + |
| 14 | +### Phase 2: Word Boundary Detection (COMMITTED) |
| 15 | +- Commit: 1b68e0a |
| 16 | +- File: `src/word-boundary.ts` (NEW) |
| 17 | +- Features: |
| 18 | + - Finds connected Arabic word boundaries |
| 19 | + - Simple algorithm: stops at non-Arabic characters |
| 20 | + - Performance: ±50 character search range |
| 21 | + |
| 22 | +### Phase 3: Context-Aware Cursor (COMMITTED) |
| 23 | +- Commit: a26c13a |
| 24 | +- File: `src/block-cursor.ts` (MODIFIED) |
| 25 | +- Features: |
| 26 | + - Latin text (focused): opaque cursor with visible text ✅ TESTED |
| 27 | + - Arabic text (focused): transparent cursor ✅ TESTED |
| 28 | + - Unfocused: outline cursor for both |
| 29 | + |
| 30 | +### Phase 4: Dual-Cursor (IMPLEMENTED BUT NOT COMMITTED) |
| 31 | +- Files modified: |
| 32 | + - `src/block-cursor.ts` - major changes |
| 33 | + - `src/script-detection.ts` - punctuation refinements |
| 34 | +- Status: **WORKING AND TESTED** ✅ |
| 35 | +- Last build: 18:22 (Nov 10) |
| 36 | + |
| 37 | +## UNCOMMITTED CHANGES (READY TO COMMIT) |
| 38 | + |
| 39 | +### 1. Update to script-detection.ts |
| 40 | +**What changed:** |
| 41 | +- Refined Arabic punctuation detection to exclude only word breakers |
| 42 | +- Diacritics (U+064B-U+065F) now correctly treated as part of letters |
| 43 | +- Spaces/whitespace explicitly excluded from connected script detection |
| 44 | + |
| 45 | +**Key code:** |
| 46 | +```typescript |
| 47 | +// Spaces and whitespace should NEVER be treated as connected script |
| 48 | +if (char === ' ' || char === '\t' || char === '\n' || char === '\r') { |
| 49 | + return { type: ScriptType.LATIN, requiresSpecialCursor: false, isConnectedScript: false }; |
| 50 | +} |
| 51 | + |
| 52 | +// Arabic punctuation (word breakers only) |
| 53 | +const isArabicPunctuation = codePoint === 0x060C || // comma |
| 54 | + codePoint === 0x061B || // semicolon |
| 55 | + codePoint === 0x061F || // question mark |
| 56 | + codePoint === 0x06D4 || // full stop |
| 57 | + // ... etc |
| 58 | +``` |
| 59 | + |
| 60 | +### 2. Update to block-cursor.ts (Phase 4 - Dual Cursor) |
| 61 | + |
| 62 | +**Major changes:** |
| 63 | + |
| 64 | +a) Added CursorLayerType enum: |
| 65 | +```typescript |
| 66 | +enum CursorLayerType { |
| 67 | + STANDARD = 'standard', |
| 68 | + ARABIC_WORD = 'arabic_word', |
| 69 | + ARABIC_CHAR = 'arabic_char' |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +b) Extended Piece class: |
| 74 | +- Added `layerType` parameter (optional, defaults to STANDARD) |
| 75 | +- Updated `eq()` method to compare layerType |
| 76 | + |
| 77 | +c) Modified `readPos()`: |
| 78 | +- Changed to spread pieces array: `cursors.push(...pieces)` |
| 79 | +- Handles multiple pieces per cursor |
| 80 | + |
| 81 | +d) Changed `measureCursor()` return type: |
| 82 | +- From: `Piece | null` |
| 83 | +- To: `Piece[] | null` |
| 84 | +- Returns array of pieces (enables multi-layer rendering) |
| 85 | + |
| 86 | +e) Added `measureArabicDualCursor()` function (NEW): |
| 87 | +- Finds word boundaries using `findArabicWordBoundaries()` |
| 88 | +- Measures word block coordinates |
| 89 | +- Creates two Piece objects: |
| 90 | + 1. Word-level block (semi-transparent pink background) |
| 91 | + 2. Character-level outline (white 1px box-shadow) |
| 92 | +- Returns `[wordPiece, charPiece]` |
| 93 | + |
| 94 | +f) Updated CSS theme: |
| 95 | +- Restored original focused cursor: `background: "#ff9696"` |
| 96 | +- Added `.cm-cursor-arabic-word` styles: |
| 97 | + - Semi-transparent background: `rgba(255, 150, 150, 0.3)` |
| 98 | + - z-index: 1 |
| 99 | +- Added `.cm-cursor-arabic-char` styles: |
| 100 | + - White outline: `boxShadow: "0 0 0 1px #ffffff"` |
| 101 | + - Transparent background |
| 102 | + - z-index: 2 |
| 103 | +- Unfocused state hides character outline |
| 104 | + |
| 105 | +g) Decision logic in measureCursor(): |
| 106 | +```typescript |
| 107 | +if (scriptDetection.requiresSpecialCursor && isFocused) { |
| 108 | + return measureArabicDualCursor(...); |
| 109 | +} else { |
| 110 | + return [new Piece(..., CursorLayerType.STANDARD)]; |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +### 3. Import additions |
| 115 | +- `src/block-cursor.ts` imports `findArabicWordBoundaries` from `./word-boundary` |
| 116 | + |
| 117 | +## TESTING RESULTS ✅ |
| 118 | + |
| 119 | +Tested with mixed Latin/Arabic text: |
| 120 | +- ✅ Latin "Hello world": White text visible in cursor (opaque) |
| 121 | +- ✅ Arabic letters: Transparent cursor + dual-cursor when focused |
| 122 | +- ✅ Arabic punctuation (comma): Standard cursor (not dual) |
| 123 | +- ✅ Spaces: Standard cursor (not dual) |
| 124 | +- ✅ Word boundaries: Correctly detected at script transitions |
| 125 | +- ✅ Navigation (h/j/k/l): Dual cursor tracks correctly through Arabic words |
| 126 | +- ✅ No skipped characters |
| 127 | + |
| 128 | +## NEXT STEPS (TODO) |
| 129 | + |
| 130 | +### 1. Commit Phase 4 |
| 131 | +```bash |
| 132 | +git add src/block-cursor.ts src/script-detection.ts |
| 133 | +git commit -m "feat: Implement dual-cursor for Arabic/connected scripts |
| 134 | +
|
| 135 | +Implements Phase 4 of the dual-cursor system architecture. |
| 136 | +
|
| 137 | +This adds hierarchical dual-cursor rendering for Arabic text: |
| 138 | +- Word-level block: Semi-transparent pink background covering entire connected word |
| 139 | +- Character-level outline: White 1px outline on specific letter under cursor |
| 140 | +
|
| 141 | +Changes: |
| 142 | +- Add CursorLayerType enum for different cursor rendering strategies |
| 143 | +- Extend Piece class with layerType parameter |
| 144 | +- Modify measureCursor() to return Piece[] for multi-layer rendering |
| 145 | +- Add measureArabicDualCursor() function for dual-layer measurement |
| 146 | +- Update CSS theme with Arabic-specific cursor styles |
| 147 | +- Refine script detection to exclude only punctuation (not diacritics) |
| 148 | +- Ensure spaces/whitespace always treated as word boundaries |
| 149 | +
|
| 150 | +Visual design: |
| 151 | +- Focused Arabic: Semi-transparent pink word block + white char outline |
| 152 | +- Focused Latin: Solid pink block with white text (opaque) |
| 153 | +- Unfocused: Pink outline for both (character outline hidden for Arabic) |
| 154 | +
|
| 155 | +Performance: Word boundary detection O(n) where n ≤ 100 characters |
| 156 | +
|
| 157 | +Tested: ✅ Dual-cursor renders correctly on Arabic text |
| 158 | +Tested: ✅ Word boundaries respect punctuation and spaces |
| 159 | +Tested: ✅ Navigation (hjkl) tracks correctly through Arabic words |
| 160 | +
|
| 161 | +Related to replit/codemirror-vim#248" |
| 162 | +``` |
| 163 | + |
| 164 | +### 2. Reapply workspace linking commit |
| 165 | +```bash |
| 166 | +# The tsconfig.json changes are already in place (uncommitted) |
| 167 | +# Just need to commit them at the end |
| 168 | +git add tsconfig.json |
| 169 | +git commit -m "feat: Add workspace paths configuration for TypeScript |
| 170 | +
|
| 171 | +Configures TypeScript paths to resolve @codemirror/* from parent |
| 172 | +node_modules, enabling proper workspace package resolution. |
| 173 | +
|
| 174 | +This allows building the vim plugin as a workspace package in the |
| 175 | +parent Zettlr repository." |
| 176 | +``` |
| 177 | + |
| 178 | +### 3. Final verification |
| 179 | +- Build: `npm run build` |
| 180 | +- Test in Zettlr with Arabic + Latin mixed text |
| 181 | +- Verify all cursor behaviors still work |
| 182 | + |
| 183 | +### 4. Update parent repo |
| 184 | +```bash |
| 185 | +cd /Users/orwa/repos/Zettlr-official |
| 186 | +git add packages/codemirror-vim |
| 187 | +git commit -m "chore: Update vim plugin submodule to dual-cursor implementation" |
| 188 | +``` |
| 189 | + |
| 190 | +## FILES CHANGED SUMMARY |
| 191 | + |
| 192 | +### New files (created in earlier phases): |
| 193 | +- `src/script-detection.ts` ✅ COMMITTED |
| 194 | +- `src/word-boundary.ts` ✅ COMMITTED |
| 195 | + |
| 196 | +### Modified files (uncommitted): |
| 197 | +- `src/block-cursor.ts` - Phase 4 dual-cursor implementation |
| 198 | +- `src/script-detection.ts` - Punctuation refinements |
| 199 | +- `tsconfig.json` - Workspace paths (for local dev only) |
| 200 | + |
| 201 | +### Build artifacts: |
| 202 | +- `dist/index.js` - Built successfully (18:22) |
| 203 | +- `dist/index.cjs` - Built successfully |
| 204 | + |
| 205 | +## KNOWN ISSUES |
| 206 | +None - all testing passed ✅ |
| 207 | + |
| 208 | +## NOTES |
| 209 | +- tsconfig.json paths configuration is for LOCAL DEVELOPMENT ONLY |
| 210 | +- Do not commit tsconfig.json to upstream PR |
| 211 | +- Type declaration errors can be ignored (JS build succeeds) |
0 commit comments