mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
markdown: Fix markdown table selection hit testing (#47720)
Release Notes: - Fixed markdown table selection hit testing Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
This commit is contained in:
parent
a1558bc5cf
commit
70c47e96bd
1 changed files with 51 additions and 2 deletions
|
|
@ -2044,19 +2044,33 @@ struct RenderedLink {
|
|||
impl RenderedText {
|
||||
fn source_index_for_position(&self, position: Point<Pixels>) -> Result<usize, usize> {
|
||||
let mut lines = self.lines.iter().peekable();
|
||||
let mut fallback_line: Option<&RenderedLine> = None;
|
||||
|
||||
while let Some(line) = lines.next() {
|
||||
let line_bounds = line.layout.bounds();
|
||||
|
||||
// Exact match: position is within bounds (handles overlapping bounds like table columns)
|
||||
if line_bounds.contains(&position) {
|
||||
return line.source_index_for_position(position);
|
||||
}
|
||||
|
||||
// Track fallback for Y-coordinate based matching
|
||||
if position.y <= line_bounds.bottom() && fallback_line.is_none() {
|
||||
fallback_line = Some(line);
|
||||
}
|
||||
|
||||
// Handle gap between lines
|
||||
if position.y > line_bounds.bottom() {
|
||||
if let Some(next_line) = lines.peek()
|
||||
&& position.y < next_line.layout.bounds().top()
|
||||
{
|
||||
return Err(line.source_end);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to Y-coordinate matched line
|
||||
if let Some(line) = fallback_line {
|
||||
return line.source_index_for_position(position);
|
||||
}
|
||||
|
||||
|
|
@ -2188,6 +2202,17 @@ mod tests {
|
|||
use language::{Language, LanguageConfig, LanguageMatcher};
|
||||
use std::sync::Arc;
|
||||
|
||||
fn ensure_theme_initialized(cx: &mut TestAppContext) {
|
||||
cx.update(|cx| {
|
||||
if !cx.has_global::<settings::SettingsStore>() {
|
||||
settings::init(cx);
|
||||
}
|
||||
if !cx.has_global::<theme::GlobalTheme>() {
|
||||
theme::init(theme::LoadThemes::JustBase, cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_mappings(cx: &mut TestAppContext) {
|
||||
// Formatting.
|
||||
|
|
@ -2256,6 +2281,8 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
ensure_theme_initialized(cx);
|
||||
|
||||
let (_, cx) = cx.add_window_view(|_, _| TestWindow);
|
||||
let markdown =
|
||||
cx.new(|cx| Markdown::new(markdown.to_string().into(), language_registry, None, cx));
|
||||
|
|
@ -2413,6 +2440,28 @@ mod tests {
|
|||
assert_eq!(selected_text, "code");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_table_column_selection(cx: &mut TestAppContext) {
|
||||
let rendered = render_markdown("| a | b |\n|---|---|\n| c | d |", cx);
|
||||
|
||||
assert!(rendered.lines.len() >= 2);
|
||||
let first_bounds = rendered.lines[0].layout.bounds();
|
||||
let second_bounds = rendered.lines[1].layout.bounds();
|
||||
|
||||
let first_index = match rendered.source_index_for_position(first_bounds.center()) {
|
||||
Ok(index) | Err(index) => index,
|
||||
};
|
||||
let second_index = match rendered.source_index_for_position(second_bounds.center()) {
|
||||
Ok(index) | Err(index) => index,
|
||||
};
|
||||
|
||||
let first_word = rendered.text_for_range(rendered.surrounding_word_range(first_index));
|
||||
let second_word = rendered.text_for_range(rendered.surrounding_word_range(second_index));
|
||||
|
||||
assert_eq!(first_word, "a");
|
||||
assert_eq!(second_word, "b");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_inline_code_word_selection_excludes_backticks(cx: &mut TestAppContext) {
|
||||
// Test that double-clicking on inline code selects just the code content,
|
||||
|
|
|
|||
Loading…
Reference in a new issue