From 173c983c6f3a84edd5ad8a68c9628845c4665f0a Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Sun, 21 Jun 2026 23:37:50 +0200 Subject: [PATCH] Working markers --- crates/analyzer/src/lib.rs | 60 ++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index 87ceec7..cece78d 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -80,16 +80,48 @@ fn byte_offset_from_lsp(source: &str, line: u32, character: u32) -> Option usize { +/// Inject a marker at the exact cursor position. If the cursor is inside or +/// at the start of an identifier-like token, the entire token is replaced with +/// the marker so parsing doesn't break from a mid-token split. +fn inject_marker_at(source: &str, line: u32, character: u32, marker: &str) -> Option { + let offset = byte_offset_from_lsp(source, line, character)?; + let before = &source[..offset]; - let trim = before + let after = &source[offset..]; + + // Identifier chars immediately before and after the cursor (as byte-counts). + let trail_bytes: usize = before .chars() .rev() .take_while(|c| c.is_alphanumeric() || *c == '_') - .count(); - offset - trim + .map(|c| c.len_utf8()) + .sum(); + let lead_bytes: usize = after + .chars() + .take_while(|c| c.is_alphanumeric() || *c == '_') + .map(|c| c.len_utf8()) + .sum(); + + if trail_bytes > 0 || lead_bytes > 0 { + // Cursor touches an identifier — replace the whole token with the marker. + let token_start = offset - trail_bytes; + let token_end = offset + lead_bytes; + + let mut s = String::with_capacity(source.len() + marker.len() + 4); + s.push_str(&source[..token_start]); + s.push_str(marker); + s.push_str(&source[token_end..]); + Some(s) + } else { + // Cursor is on whitespace / punctuation — inject as standalone expression. + let mut s = String::with_capacity(source.len() + marker.len() + 4); + s.push_str(&source[..offset]); + s.push(' '); + s.push_str(marker); + s.push(' '); + s.push_str(&source[offset..]); + Some(s) + } } fn find_marker_position(content: &str, marker: &str) -> Option { @@ -160,15 +192,13 @@ impl Backend { let id = MARKER_COUNTER.fetch_add(1, Ordering::Relaxed); let marker = format!("__mist_mk{id:x}__"); - let offset = byte_offset_from_lsp(source, line, character)?; - let offset = snap_to_word_start(source, offset); - - let mut modified = String::with_capacity(source.len() + marker.len() + 4); - modified.push_str(&source[..offset]); - modified.push(' '); - modified.push_str(&marker); - modified.push(' '); - modified.push_str(&source[offset..]); + let modified = match inject_marker_at(source, line, character, &marker) { + Some(m) => m, + None => { + eprintln!("[marker] inject_marker_at returned None for LSP({line},{character})"); + return None; + } + }; let transpiled = match transpile_mist(mist_path, &modified, extra_mod_decl) { Ok(t) => t,