using ropey

This commit is contained in:
2026-05-24 16:24:22 +02:00
parent 5a6adbc5e4
commit fbf60944a8
3 changed files with 49 additions and 24 deletions
Generated
+17
View File
@@ -448,6 +448,7 @@ dependencies = [
"dashmap 6.1.0", "dashmap 6.1.0",
"mist-codegen", "mist-codegen",
"mist-parser", "mist-parser",
"ropey",
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
@@ -623,6 +624,16 @@ dependencies = [
"bitflags 2.11.1", "bitflags 2.11.1",
] ]
[[package]]
name = "ropey"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93411e420bcd1a75ddd1dc3caf18c23155eda2c090631a85af21ba19e97093b5"
dependencies = [
"smallvec",
"str_indices",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@@ -742,6 +753,12 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
name = "str_indices"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.117" version = "2.0.117"
+1
View File
@@ -19,3 +19,4 @@ cargo_metadata = "0.23.1"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
ropey = "1"
+31 -24
View File
@@ -8,6 +8,7 @@ use std::path::{Component, PathBuf};
use std::sync::Arc; use std::sync::Arc;
use mist_parser::rev_mapper; use mist_parser::rev_mapper;
use ropey::Rope;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tower_lsp::jsonrpc::Result; use tower_lsp::jsonrpc::Result;
use tower_lsp::lsp_types::notification::Notification; use tower_lsp::lsp_types::notification::Notification;
@@ -539,44 +540,50 @@ pub fn from_rust_to_mist(mut path: PathBuf) -> PathBuf {
} }
fn insert_at_position(s: &str, line: usize, col: usize, insert: &str) -> String { fn insert_at_position(s: &str, line: usize, col: usize, insert: &str) -> String {
let mut lines: Vec<String> = s.lines().map(|l| l.to_string()).collect(); let mut rope = Rope::from_str(s);
// Convert to 0-index // Convert to 0-indexed
let line_idx = line.saturating_sub(1); let line_idx = line.saturating_sub(1);
let col_idx = col.saturating_sub(1); let col_idx = col.saturating_sub(1);
// Ensure line exists (optional behavior: extend with empty lines) // Clamp line
if line_idx >= lines.len() { let line_idx = line_idx.min(rope.len_lines().saturating_sub(1));
lines.resize(line_idx + 1, String::new());
}
let target = &mut lines[line_idx]; // Get start char index of the line
let line_start = rope.line_to_char(line_idx);
// Clamp column to valid char boundary // Get line length in chars
let char_idx = target let line = rope.line(line_idx);
.char_indices() let line_len = line.len_chars();
.nth(col_idx)
.map(|(i, _)| i)
.unwrap_or(target.len()); // if past end, append
target.insert_str(char_idx, insert); // Clamp column
let col_idx = col_idx.min(line_len);
lines.join("\n") // Final insertion char index
let insert_idx = line_start + col_idx;
rope.insert(insert_idx, insert);
rope.to_string()
} }
fn find_row_col(output: &str, inject: &str) -> Option<(usize, usize)> { fn find_row_col(output: &str, inject: &str) -> Option<(usize, usize)> {
// 1. Find the flat byte index just like your original code let rope = Rope::from_str(output);
let byte_idx = output.find(inject)?; let byte_idx = output.find(inject)?;
// 2. Slice the string up to the match point // Convert byte index -> char index
let prefix = &output[..byte_idx]; let char_idx = output[..byte_idx].chars().count();
// 3. Row = number of newlines found before the match + 1 (1-indexed) // Ropey line lookup
let row = prefix.lines().count(); let line_idx = rope.char_to_line(char_idx);
// 4. Column = character count of the remaining text on the current line + 1 // Line start char index
// (Using .chars().count() ensures it works with multi-byte UTF-8 symbols) let line_start = rope.line_to_char(line_idx);
let col = prefix.lines().last().unwrap_or("").chars().count() + 1;
Some((row, col)) // Column within line
let col_idx = char_idx - line_start;
// Return 1-indexed
Some((line_idx + 1, col_idx + 1))
} }