You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
Yogthos
committed
fix(ui): B3-8 — display-width-aware cursor + mouse selection for CJK/emoji
Two paths previously treated CHAR count as display-cell count:
1. wrap_input (renderer.rs:1457-1497) compared cursor_display_col
to chars().count() when deciding whether the cursor sits at
end-of-line. For "日本" with cursor at the end, col=4 (4 display
cells) but char_count=2 — the comparison failed and the cursor
wrapped onto a phantom row 1.
2. buffer_pos_at (renderer.rs:266-277) clamped the click column
to chars().count(). For wide-char lines, a click mid-line
landed at the wrong char position, dragging clipboard selection
ranges across the wrong glyphs.
Fix:
- wrap_input now also computes UnicodeWidthStr::width(line) and
compares against THAT for the end-of-line cursor branch.
- New display_col_to_char_index helper walks chars accumulating
UnicodeWidthChar::width until reaching the target display col;
buffer_pos_at uses it. Clicks in the middle of a 2-cell glyph
anchor at the glyph's START so the selection boundary lands on
a real grapheme.
What this DOESN'T fix: soft-wrap slicing for very long CJK lines
that need to break mid-row. Current row count + char_start/char_end
remain in char units, so a CJK line wider than wrap_width still
splits at a char boundary but may overflow display cells on a
single row. Filed as future work; rare in practice given typical
input widths.
Tests: 3 new (ascii round-trip, CJK compression, emoji widths).
1095 → 1098 with plugin / 890 → 893 without.
Closes dirge-yep. B3-9 (edit fuzzy cascade) + B3-10 (LSP pull)
remain.
Copy file name to clipboardExpand all lines: .beads/issues.jsonl
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -15,9 +15,9 @@
15
15
{"_type":"issue","id":"dirge-86e","title":"ANSI injection in permission ALERT prompt","description":"ask_req.tool / ask_req.input rendered un-sanitized at mod.rs:2584-2585. Reopen path already sanitizes — asymmetric. Sec impl: ANSI at the permission-decision moment.","status":"closed","priority":1,"issue_type":"bug","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-05-21T22:17:34Z","created_by":"Yogthos","updated_at":"2026-05-21T22:26:37Z","started_at":"2026-05-21T22:17:42Z","closed_at":"2026-05-21T22:26:37Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
16
16
{"_type":"issue","id":"dirge-9f1","title":"Chat history ignores 120-col content_width cap","description":"max_line_width and wrap_line use raw content_cols, so on wide terminals scrollback overflows the centered band into divider/panel margin.","status":"closed","priority":1,"issue_type":"bug","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-05-21T22:17:33Z","created_by":"Yogthos","updated_at":"2026-05-21T22:26:36Z","started_at":"2026-05-21T22:17:42Z","closed_at":"2026-05-21T22:26:36Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
17
17
{"_type":"issue","id":"dirge-woq","title":"R1: fix 3 critical plugin bugs (FFI panic, dialog deadlock, init hang)","description":"From the plugin subsystem audit: (1) wrap JanetCFunctions in catch_unwind so Rust panics don't unwind across the C-FFI boundary into Janet; (2) cancel send_dialog's reply_rx.recv() on worker shutdown so the worker thread doesn't block forever when the UI exits mid-dialog; (3) add timeout to the init handshake so a worker panic before init_tx.send() doesn't hang the main thread. Also: (4) bounds-assert wrap_string's i32 cast for the unlikely \u003e2GB case, (5) make take_string_slot atomic to close the race window, (6) don't eat unrelated user events in the dialog arm.","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-05-20T14:59:57Z","created_by":"Yogthos","updated_at":"2026-05-20T15:30:28Z","started_at":"2026-05-20T15:00:10Z","closed_at":"2026-05-20T15:30:28Z","dependency_count":0,"dependent_count":1,"comment_count":0}
18
-
{"_type":"issue","id":"dirge-84j","title":"B3-9: edit tool fuzzy-match cascade","description":"edit.rs:155-160 returns 'old_text not found' on whitespace/indent/CRLF drift. LLMs frequently hit this. opencode edit.ts:222-432 has simple → lineTrimmed → whitespace-normalized → indentation-flexible → levenshtein. pi edit-diff.ts:91-132 has fuzzyFindText. Port the cascade.","status":"open","priority":2,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-05-23T03:24:44Z","created_by":"Yogthos","updated_at":"2026-05-23T03:24:44Z","dependency_count":0,"dependent_count":0,"comment_count":0}
18
+
{"_type":"issue","id":"dirge-84j","title":"B3-9: edit tool fuzzy-match cascade","description":"edit.rs:155-160 returns 'old_text not found' on whitespace/indent/CRLF drift. LLMs frequently hit this. opencode edit.ts:222-432 has simple → lineTrimmed → whitespace-normalized → indentation-flexible → levenshtein. pi edit-diff.ts:91-132 has fuzzyFindText. Port the cascade.","status":"in_progress","priority":2,"issue_type":"feature","assignee":"Yogthos","owner":"yogthos@gmail.com","created_at":"2026-05-23T03:24:44Z","created_by":"Yogthos","updated_at":"2026-05-23T03:37:16Z","started_at":"2026-05-23T03:37:16Z","dependency_count":0,"dependent_count":0,"comment_count":0}
19
19
{"_type":"issue","id":"dirge-ims","title":"B3-10: LSP pull-diagnostic fallback for lazy servers","description":"lsp/client.rs:261-289 wait_for_push is push-only. clojure-lsp/jdtls/clangd may not push on demand. 10s timeout = 'clean' diagnostic block reported when errors exist. opencode lsp/client.ts:540-582 races push-wait against requestDocumentDiagnostics. Add pull fallback.","status":"open","priority":2,"issue_type":"feature","owner":"yogthos@gmail.com","created_at":"2026-05-23T03:24:44Z","created_by":"Yogthos","updated_at":"2026-05-23T03:24:44Z","dependency_count":0,"dependent_count":0,"comment_count":0}
20
-
{"_type":"issue","id":"dirge-yep","title":"B3-8: soft-wrap + mouse selection display-width awareness","description":"renderer.rs:1457-1496 wrap_input measures chars().count() instead of UnicodeWidthChar. Cursor mis-lands on CJK/emoji wrapped lines. Mouse selection columns map 1:1 char-to-display rather than width-aware. Pi interactive-mode.ts uses string-width per cell.","status":"open","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-05-23T03:24:43Z","created_by":"Yogthos","updated_at":"2026-05-23T03:24:43Z","dependency_count":0,"dependent_count":0,"comment_count":0}
20
+
{"_type":"issue","id":"dirge-yep","title":"B3-8: soft-wrap + mouse selection display-width awareness","description":"renderer.rs:1457-1496 wrap_input measures chars().count() instead of UnicodeWidthChar. Cursor mis-lands on CJK/emoji wrapped lines. Mouse selection columns map 1:1 char-to-display rather than width-aware. Pi interactive-mode.ts uses string-width per cell.","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-05-23T03:24:43Z","created_by":"Yogthos","updated_at":"2026-05-23T03:37:14Z","closed_at":"2026-05-23T03:37:14Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
21
21
{"_type":"issue","id":"dirge-0nk","title":"B3-7: Python find_callees captures method calls","description":"semantic/adapters/python.rs:280 only matches (call function:(identifier)); misses obj.method(). Go/Java/C++ all capture selector_expression equivalent. Python users get hollow callee lists.","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-05-23T03:24:42Z","created_by":"Yogthos","updated_at":"2026-05-23T03:33:51Z","closed_at":"2026-05-23T03:33:51Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
22
22
{"_type":"issue","id":"dirge-8lj","title":"B3-5: doom-loop + allowlist reset on /cd","description":"permission/checker.rs:568-571 only updates cwd. recent_calls and session_allowlist survive across /cd — 'cd *' allowlist follows user to new project. Clear both on set_working_dir.","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-05-23T03:24:41Z","created_by":"Yogthos","updated_at":"2026-05-23T03:33:50Z","closed_at":"2026-05-23T03:33:50Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
23
23
{"_type":"issue","id":"dirge-9ar","title":"B3-6: bash background \u0026 in fallback splitter + AST recurse","description":"bash.rs:401-473 fallback splitter (no semantic-bash feature) doesn't split on bare \u0026. Also semantic-bash should recurse so background commands get checked individually.","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-05-23T03:24:41Z","created_by":"Yogthos","updated_at":"2026-05-23T03:33:50Z","closed_at":"2026-05-23T03:33:50Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
0 commit comments