git: Fix a couple of bugs with buffer headers in the side-by-side diff UI (#47809)

Cole Miller created

- Fix sticky buffer header being painted on top of the toolbar
- Fix buffer header click handlers and tooltips sometimes not working
(element ID collision issue)
- Deduplicate buffer header rendering code between split and normal
editors

Release Notes:

- N/A

Change summary

crates/editor/src/element.rs           | 833 ++++++++++++++-------------
crates/editor/src/split_editor_view.rs | 534 +----------------
2 files changed, 462 insertions(+), 905 deletions(-)

Detailed changes

crates/editor/src/element.rs 🔗

@@ -4092,421 +4092,16 @@ impl EditorElement {
         window: &mut Window,
         cx: &mut App,
     ) -> impl IntoElement {
-        let editor = self.editor.read(cx);
-        let multi_buffer = editor.buffer.read(cx);
-        let is_read_only = self.editor.read(cx).read_only(cx);
-        let editor_handle: &dyn ItemHandle = &self.editor;
-
-        let breadcrumbs = if is_selected {
-            editor.breadcrumbs_inner(cx.theme(), cx)
-        } else {
-            None
-        };
-
-        let file_status = multi_buffer
-            .all_diff_hunks_expanded()
-            .then(|| editor.status_for_buffer_id(for_excerpt.buffer_id, cx))
-            .flatten();
-        let indicator = multi_buffer
-            .buffer(for_excerpt.buffer_id)
-            .and_then(|buffer| {
-                let buffer = buffer.read(cx);
-                let indicator_color = match (buffer.has_conflict(), buffer.is_dirty()) {
-                    (true, _) => Some(Color::Warning),
-                    (_, true) => Some(Color::Accent),
-                    (false, false) => None,
-                };
-                indicator_color.map(|indicator_color| Indicator::dot().color(indicator_color))
-            });
-
-        let include_root = editor
-            .project
-            .as_ref()
-            .map(|project| project.read(cx).visible_worktrees(cx).count() > 1)
-            .unwrap_or_default();
-        let file = for_excerpt.buffer.file();
-        let can_open_excerpts = file.is_none_or(|file| file.can_open());
-        let path_style = file.map(|file| file.path_style(cx));
-        let relative_path = for_excerpt.buffer.resolve_file_path(include_root, cx);
-        let (parent_path, filename) = if let Some(path) = &relative_path {
-            if let Some(path_style) = path_style {
-                let (dir, file_name) = path_style.split(path);
-                (dir.map(|dir| dir.to_owned()), Some(file_name.to_owned()))
-            } else {
-                (None, Some(path.clone()))
-            }
-        } else {
-            (None, None)
-        };
-        let focus_handle = editor.focus_handle(cx);
-        let colors = cx.theme().colors();
-
-        let header = div()
-            .p_1()
-            .w_full()
-            .h(FILE_HEADER_HEIGHT as f32 * window.line_height())
-            .child(
-                h_flex()
-                    .size_full()
-                    .flex_basis(Length::Definite(DefiniteLength::Fraction(0.667)))
-                    .pl_1()
-                    .pr_2()
-                    .rounded_sm()
-                    .gap_1p5()
-                    .when(is_sticky, |el| el.shadow_md())
-                    .border_1()
-                    .map(|border| {
-                        let border_color = if is_selected
-                            && is_folded
-                            && focus_handle.contains_focused(window, cx)
-                        {
-                            colors.border_focused
-                        } else {
-                            colors.border
-                        };
-                        border.border_color(border_color)
-                    })
-                    .bg(colors.editor_subheader_background)
-                    .hover(|style| style.bg(colors.element_hover))
-                    .map(|header| {
-                        let editor = self.editor.clone();
-                        let buffer_id = for_excerpt.buffer_id;
-                        let toggle_chevron_icon =
-                            FileIcons::get_chevron_icon(!is_folded, cx).map(Icon::from_path);
-                        let button_size = rems_from_px(28.);
-
-                        header.child(
-                            div()
-                                .hover(|style| style.bg(colors.element_selected))
-                                .rounded_xs()
-                                .child(
-                                    ButtonLike::new("toggle-buffer-fold")
-                                        .style(ButtonStyle::Transparent)
-                                        .height(button_size.into())
-                                        .width(button_size)
-                                        .children(toggle_chevron_icon)
-                                        .tooltip({
-                                            let focus_handle = focus_handle.clone();
-                                            let is_folded_for_tooltip = is_folded;
-                                            move |_window, cx| {
-                                                Tooltip::with_meta_in(
-                                                    if is_folded_for_tooltip {
-                                                        "Unfold Excerpt"
-                                                    } else {
-                                                        "Fold Excerpt"
-                                                    },
-                                                    Some(&ToggleFold),
-                                                    format!(
-                                                        "{} to toggle all",
-                                                        text_for_keystroke(
-                                                            &Modifiers::alt(),
-                                                            "click",
-                                                            cx
-                                                        )
-                                                    ),
-                                                    &focus_handle,
-                                                    cx,
-                                                )
-                                            }
-                                        })
-                                        .on_click(move |event, window, cx| {
-                                            if event.modifiers().alt {
-                                                // Alt+click toggles all buffers
-                                                editor.update(cx, |editor, cx| {
-                                                    editor.toggle_fold_all(
-                                                        &ToggleFoldAll,
-                                                        window,
-                                                        cx,
-                                                    );
-                                                });
-                                            } else {
-                                                // Regular click toggles single buffer
-                                                if is_folded {
-                                                    editor.update(cx, |editor, cx| {
-                                                        editor.unfold_buffer(buffer_id, cx);
-                                                    });
-                                                } else {
-                                                    editor.update(cx, |editor, cx| {
-                                                        editor.fold_buffer(buffer_id, cx);
-                                                    });
-                                                }
-                                            }
-                                        }),
-                                ),
-                        )
-                    })
-                    .children(
-                        editor
-                            .addons
-                            .values()
-                            .filter_map(|addon| {
-                                addon.render_buffer_header_controls(for_excerpt, window, cx)
-                            })
-                            .take(1),
-                    )
-                    .when(!is_read_only, |this| {
-                        this.child(
-                            h_flex()
-                                .size_3()
-                                .justify_center()
-                                .flex_shrink_0()
-                                .children(indicator),
-                        )
-                    })
-                    .child(
-                        h_flex()
-                            .cursor_pointer()
-                            .id("path_header_block")
-                            .min_w_0()
-                            .size_full()
-                            .gap_1()
-                            .justify_between()
-                            .overflow_hidden()
-                            .child(h_flex().min_w_0().flex_1().gap_0p5().overflow_hidden().map(
-                                |path_header| {
-                                    let filename = filename
-                                        .map(SharedString::from)
-                                        .unwrap_or_else(|| "untitled".into());
-
-                                    let full_path = match parent_path.as_deref() {
-                                        Some(parent) if !parent.is_empty() => {
-                                            format!("{}{}", parent, filename.as_str())
-                                        }
-                                        _ => filename.as_str().to_string(),
-                                    };
-
-                                    path_header
-                                        .child(
-                                            ButtonLike::new("filename-button")
-                                                .when(
-                                                    ItemSettings::get_global(cx).file_icons,
-                                                    |this| {
-                                                        let path =
-                                                            path::Path::new(filename.as_str());
-                                                        let icon = FileIcons::get_icon(path, cx)
-                                                            .unwrap_or_default();
-
-                                                        this.child(
-                                                            Icon::from_path(icon)
-                                                                .color(Color::Muted),
-                                                        )
-                                                    },
-                                                )
-                                                .child(
-                                                    Label::new(filename)
-                                                        .single_line()
-                                                        .color(file_status_label_color(file_status))
-                                                        .buffer_font(cx)
-                                                        .when(
-                                                            file_status
-                                                                .is_some_and(|s| s.is_deleted()),
-                                                            |label| label.strikethrough(),
-                                                        ),
-                                                )
-                                                .tooltip(move |_, cx| {
-                                                    Tooltip::with_meta(
-                                                        "Open File",
-                                                        None,
-                                                        full_path.clone(),
-                                                        cx,
-                                                    )
-                                                })
-                                                .on_click(window.listener_for(&self.editor, {
-                                                    let jump_data = jump_data.clone();
-                                                    move |editor, e: &ClickEvent, window, cx| {
-                                                        editor.open_excerpts_common(
-                                                            Some(jump_data.clone()),
-                                                            e.modifiers().secondary(),
-                                                            window,
-                                                            cx,
-                                                        );
-                                                    }
-                                                })),
-                                        )
-                                        .when_some(parent_path, |then, path| {
-                                            then.child(
-                                                Label::new(path)
-                                                    .buffer_font(cx)
-                                                    .truncate_start()
-                                                    .color(
-                                                        if file_status
-                                                            .is_some_and(FileStatus::is_deleted)
-                                                        {
-                                                            Color::Custom(colors.text_disabled)
-                                                        } else {
-                                                            Color::Custom(colors.text_muted)
-                                                        },
-                                                    ),
-                                            )
-                                        })
-                                        .when(!for_excerpt.buffer.capability.editable(), |el| {
-                                            el.child(
-                                                Icon::new(IconName::FileLock).color(Color::Muted),
-                                            )
-                                        })
-                                        .when_some(breadcrumbs, |then, breadcrumbs| {
-                                            then.child(render_breadcrumb_text(
-                                                breadcrumbs,
-                                                None,
-                                                editor_handle,
-                                                true,
-                                                window,
-                                                cx,
-                                            ))
-                                        })
-                                },
-                            ))
-                            .when(
-                                can_open_excerpts && is_selected && relative_path.is_some(),
-                                |el| {
-                                    el.child(
-                                        Button::new("open-file-button", "Open File")
-                                            .style(ButtonStyle::OutlinedGhost)
-                                            .key_binding(KeyBinding::for_action_in(
-                                                &OpenExcerpts,
-                                                &focus_handle,
-                                                cx,
-                                            ))
-                                            .on_click(window.listener_for(&self.editor, {
-                                                let jump_data = jump_data.clone();
-                                                move |editor, e: &ClickEvent, window, cx| {
-                                                    editor.open_excerpts_common(
-                                                        Some(jump_data.clone()),
-                                                        e.modifiers().secondary(),
-                                                        window,
-                                                        cx,
-                                                    );
-                                                }
-                                            })),
-                                    )
-                                },
-                            )
-                            .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
-                            .on_click(window.listener_for(&self.editor, {
-                                let buffer_id = for_excerpt.buffer_id;
-                                move |editor, e: &ClickEvent, window, cx| {
-                                    if e.modifiers().alt {
-                                        editor.open_excerpts_common(
-                                            Some(jump_data.clone()),
-                                            e.modifiers().secondary(),
-                                            window,
-                                            cx,
-                                        );
-                                        return;
-                                    }
-
-                                    if is_folded {
-                                        editor.unfold_buffer(buffer_id, cx);
-                                    } else {
-                                        editor.fold_buffer(buffer_id, cx);
-                                    }
-                                }
-                            })),
-                    ),
-            );
-
-        let file = for_excerpt.buffer.file().cloned();
-        let editor = self.editor.clone();
-
-        right_click_menu("buffer-header-context-menu")
-            .trigger(move |_, _, _| header)
-            .menu(move |window, cx| {
-                let menu_context = focus_handle.clone();
-                let editor = editor.clone();
-                let file = file.clone();
-                ContextMenu::build(window, cx, move |mut menu, window, cx| {
-                    if let Some(file) = file
-                        && let Some(project) = editor.read(cx).project()
-                        && let Some(worktree) =
-                            project.read(cx).worktree_for_id(file.worktree_id(cx), cx)
-                    {
-                        let path_style = file.path_style(cx);
-                        let worktree = worktree.read(cx);
-                        let relative_path = file.path();
-                        let entry_for_path = worktree.entry_for_path(relative_path);
-                        let abs_path = entry_for_path.map(|e| {
-                            e.canonical_path.as_deref().map_or_else(
-                                || worktree.absolutize(relative_path),
-                                Path::to_path_buf,
-                            )
-                        });
-                        let has_relative_path = worktree.root_entry().is_some_and(Entry::is_dir);
-
-                        let parent_abs_path = abs_path
-                            .as_ref()
-                            .and_then(|abs_path| Some(abs_path.parent()?.to_path_buf()));
-                        let relative_path = has_relative_path
-                            .then_some(relative_path)
-                            .map(ToOwned::to_owned);
-
-                        let visible_in_project_panel =
-                            relative_path.is_some() && worktree.is_visible();
-                        let reveal_in_project_panel = entry_for_path
-                            .filter(|_| visible_in_project_panel)
-                            .map(|entry| entry.id);
-                        menu = menu
-                            .when_some(abs_path, |menu, abs_path| {
-                                menu.entry(
-                                    "Copy Path",
-                                    Some(Box::new(zed_actions::workspace::CopyPath)),
-                                    window.handler_for(&editor, move |_, _, cx| {
-                                        cx.write_to_clipboard(ClipboardItem::new_string(
-                                            abs_path.to_string_lossy().into_owned(),
-                                        ));
-                                    }),
-                                )
-                            })
-                            .when_some(relative_path, |menu, relative_path| {
-                                menu.entry(
-                                    "Copy Relative Path",
-                                    Some(Box::new(zed_actions::workspace::CopyRelativePath)),
-                                    window.handler_for(&editor, move |_, _, cx| {
-                                        cx.write_to_clipboard(ClipboardItem::new_string(
-                                            relative_path.display(path_style).to_string(),
-                                        ));
-                                    }),
-                                )
-                            })
-                            .when(
-                                reveal_in_project_panel.is_some() || parent_abs_path.is_some(),
-                                |menu| menu.separator(),
-                            )
-                            .when_some(reveal_in_project_panel, |menu, entry_id| {
-                                menu.entry(
-                                    "Reveal In Project Panel",
-                                    Some(Box::new(RevealInProjectPanel::default())),
-                                    window.handler_for(&editor, move |editor, _, cx| {
-                                        if let Some(project) = &mut editor.project {
-                                            project.update(cx, |_, cx| {
-                                                cx.emit(project::Event::RevealInProjectPanel(
-                                                    entry_id,
-                                                ))
-                                            });
-                                        }
-                                    }),
-                                )
-                            })
-                            .when_some(parent_abs_path, |menu, parent_abs_path| {
-                                menu.entry(
-                                    "Open in Terminal",
-                                    Some(Box::new(OpenInTerminal)),
-                                    window.handler_for(&editor, move |_, window, cx| {
-                                        window.dispatch_action(
-                                            OpenTerminal {
-                                                working_directory: parent_abs_path.clone(),
-                                                local: false,
-                                            }
-                                            .boxed_clone(),
-                                            cx,
-                                        );
-                                    }),
-                                )
-                            });
-                    }
-
-                    menu.context(menu_context)
-                })
-            })
+        render_buffer_header(
+            &self.editor,
+            for_excerpt,
+            is_folded,
+            is_selected,
+            is_sticky,
+            jump_data,
+            window,
+            cx,
+        )
     }
 
     fn render_blocks(
@@ -8441,6 +8036,414 @@ fn header_jump_data_inner(
     }
 }
 
+pub(crate) fn render_buffer_header(
+    editor: &Entity<Editor>,
+    for_excerpt: &ExcerptInfo,
+    is_folded: bool,
+    is_selected: bool,
+    is_sticky: bool,
+    jump_data: JumpData,
+    window: &mut Window,
+    cx: &mut App,
+) -> impl IntoElement {
+    let editor_read = editor.read(cx);
+    let multi_buffer = editor_read.buffer.read(cx);
+    let is_read_only = editor_read.read_only(cx);
+    let editor_handle: &dyn ItemHandle = editor;
+
+    let breadcrumbs = if is_selected {
+        editor_read.breadcrumbs_inner(cx.theme(), cx)
+    } else {
+        None
+    };
+
+    let file_status = multi_buffer
+        .all_diff_hunks_expanded()
+        .then(|| editor_read.status_for_buffer_id(for_excerpt.buffer_id, cx))
+        .flatten();
+    let indicator = multi_buffer
+        .buffer(for_excerpt.buffer_id)
+        .and_then(|buffer| {
+            let buffer = buffer.read(cx);
+            let indicator_color = match (buffer.has_conflict(), buffer.is_dirty()) {
+                (true, _) => Some(Color::Warning),
+                (_, true) => Some(Color::Accent),
+                (false, false) => None,
+            };
+            indicator_color.map(|indicator_color| Indicator::dot().color(indicator_color))
+        });
+
+    let include_root = editor_read
+        .project
+        .as_ref()
+        .map(|project| project.read(cx).visible_worktrees(cx).count() > 1)
+        .unwrap_or_default();
+    let file = for_excerpt.buffer.file();
+    let can_open_excerpts = file.is_none_or(|file| file.can_open());
+    let path_style = file.map(|file| file.path_style(cx));
+    let relative_path = for_excerpt.buffer.resolve_file_path(include_root, cx);
+    let (parent_path, filename) = if let Some(path) = &relative_path {
+        if let Some(path_style) = path_style {
+            let (dir, file_name) = path_style.split(path);
+            (dir.map(|dir| dir.to_owned()), Some(file_name.to_owned()))
+        } else {
+            (None, Some(path.clone()))
+        }
+    } else {
+        (None, None)
+    };
+    let focus_handle = editor_read.focus_handle(cx);
+    let colors = cx.theme().colors();
+
+    let header = div()
+        .id(("buffer-header", for_excerpt.buffer_id.to_proto()))
+        .p_1()
+        .w_full()
+        .h(FILE_HEADER_HEIGHT as f32 * window.line_height())
+        .child(
+            h_flex()
+                .size_full()
+                .flex_basis(Length::Definite(DefiniteLength::Fraction(0.667)))
+                .pl_1()
+                .pr_2()
+                .rounded_sm()
+                .gap_1p5()
+                .when(is_sticky, |el| el.shadow_md())
+                .border_1()
+                .map(|border| {
+                    let border_color =
+                        if is_selected && is_folded && focus_handle.contains_focused(window, cx) {
+                            colors.border_focused
+                        } else {
+                            colors.border
+                        };
+                    border.border_color(border_color)
+                })
+                .bg(colors.editor_subheader_background)
+                .hover(|style| style.bg(colors.element_hover))
+                .map(|header| {
+                    let editor = editor.clone();
+                    let buffer_id = for_excerpt.buffer_id;
+                    let toggle_chevron_icon =
+                        FileIcons::get_chevron_icon(!is_folded, cx).map(Icon::from_path);
+                    let button_size = rems_from_px(28.);
+
+                    header.child(
+                        div()
+                            .hover(|style| style.bg(colors.element_selected))
+                            .rounded_xs()
+                            .child(
+                                ButtonLike::new("toggle-buffer-fold")
+                                    .style(ButtonStyle::Transparent)
+                                    .height(button_size.into())
+                                    .width(button_size)
+                                    .children(toggle_chevron_icon)
+                                    .tooltip({
+                                        let focus_handle = focus_handle.clone();
+                                        let is_folded_for_tooltip = is_folded;
+                                        move |_window, cx| {
+                                            Tooltip::with_meta_in(
+                                                if is_folded_for_tooltip {
+                                                    "Unfold Excerpt"
+                                                } else {
+                                                    "Fold Excerpt"
+                                                },
+                                                Some(&ToggleFold),
+                                                format!(
+                                                    "{} to toggle all",
+                                                    text_for_keystroke(
+                                                        &Modifiers::alt(),
+                                                        "click",
+                                                        cx
+                                                    )
+                                                ),
+                                                &focus_handle,
+                                                cx,
+                                            )
+                                        }
+                                    })
+                                    .on_click(move |event, window, cx| {
+                                        if event.modifiers().alt {
+                                            editor.update(cx, |editor, cx| {
+                                                editor.toggle_fold_all(&ToggleFoldAll, window, cx);
+                                            });
+                                        } else {
+                                            if is_folded {
+                                                editor.update(cx, |editor, cx| {
+                                                    editor.unfold_buffer(buffer_id, cx);
+                                                });
+                                            } else {
+                                                editor.update(cx, |editor, cx| {
+                                                    editor.fold_buffer(buffer_id, cx);
+                                                });
+                                            }
+                                        }
+                                    }),
+                            ),
+                    )
+                })
+                .children(
+                    editor_read
+                        .addons
+                        .values()
+                        .filter_map(|addon| {
+                            addon.render_buffer_header_controls(for_excerpt, window, cx)
+                        })
+                        .take(1),
+                )
+                .when(!is_read_only, |this| {
+                    this.child(
+                        h_flex()
+                            .size_3()
+                            .justify_center()
+                            .flex_shrink_0()
+                            .children(indicator),
+                    )
+                })
+                .child(
+                    h_flex()
+                        .cursor_pointer()
+                        .id("path_header_block")
+                        .min_w_0()
+                        .size_full()
+                        .gap_1()
+                        .justify_between()
+                        .overflow_hidden()
+                        .child(h_flex().min_w_0().flex_1().gap_0p5().overflow_hidden().map(
+                            |path_header| {
+                                let filename = filename
+                                    .map(SharedString::from)
+                                    .unwrap_or_else(|| "untitled".into());
+
+                                let full_path = match parent_path.as_deref() {
+                                    Some(parent) if !parent.is_empty() => {
+                                        format!("{}{}", parent, filename.as_str())
+                                    }
+                                    _ => filename.as_str().to_string(),
+                                };
+
+                                path_header
+                                    .child(
+                                        ButtonLike::new("filename-button")
+                                            .when(ItemSettings::get_global(cx).file_icons, |this| {
+                                                let path = path::Path::new(filename.as_str());
+                                                let icon = FileIcons::get_icon(path, cx)
+                                                    .unwrap_or_default();
+
+                                                this.child(
+                                                    Icon::from_path(icon).color(Color::Muted),
+                                                )
+                                            })
+                                            .child(
+                                                Label::new(filename)
+                                                    .single_line()
+                                                    .color(file_status_label_color(file_status))
+                                                    .buffer_font(cx)
+                                                    .when(
+                                                        file_status.is_some_and(|s| s.is_deleted()),
+                                                        |label| label.strikethrough(),
+                                                    ),
+                                            )
+                                            .tooltip(move |_, cx| {
+                                                Tooltip::with_meta(
+                                                    "Open File",
+                                                    None,
+                                                    full_path.clone(),
+                                                    cx,
+                                                )
+                                            })
+                                            .on_click(window.listener_for(editor, {
+                                                let jump_data = jump_data.clone();
+                                                move |editor, e: &ClickEvent, window, cx| {
+                                                    editor.open_excerpts_common(
+                                                        Some(jump_data.clone()),
+                                                        e.modifiers().secondary(),
+                                                        window,
+                                                        cx,
+                                                    );
+                                                }
+                                            })),
+                                    )
+                                    .when_some(parent_path, |then, path| {
+                                        then.child(
+                                            Label::new(path)
+                                                .buffer_font(cx)
+                                                .truncate_start()
+                                                .color(
+                                                    if file_status
+                                                        .is_some_and(FileStatus::is_deleted)
+                                                    {
+                                                        Color::Custom(colors.text_disabled)
+                                                    } else {
+                                                        Color::Custom(colors.text_muted)
+                                                    },
+                                                ),
+                                        )
+                                    })
+                                    .when(!for_excerpt.buffer.capability.editable(), |el| {
+                                        el.child(Icon::new(IconName::FileLock).color(Color::Muted))
+                                    })
+                                    .when_some(breadcrumbs, |then, breadcrumbs| {
+                                        then.child(render_breadcrumb_text(
+                                            breadcrumbs,
+                                            None,
+                                            editor_handle,
+                                            true,
+                                            window,
+                                            cx,
+                                        ))
+                                    })
+                            },
+                        ))
+                        .when(
+                            can_open_excerpts && is_selected && relative_path.is_some(),
+                            |el| {
+                                el.child(
+                                    Button::new("open-file-button", "Open File")
+                                        .style(ButtonStyle::OutlinedGhost)
+                                        .key_binding(KeyBinding::for_action_in(
+                                            &OpenExcerpts,
+                                            &focus_handle,
+                                            cx,
+                                        ))
+                                        .on_click(window.listener_for(editor, {
+                                            let jump_data = jump_data.clone();
+                                            move |editor, e: &ClickEvent, window, cx| {
+                                                editor.open_excerpts_common(
+                                                    Some(jump_data.clone()),
+                                                    e.modifiers().secondary(),
+                                                    window,
+                                                    cx,
+                                                );
+                                            }
+                                        })),
+                                )
+                            },
+                        )
+                        .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
+                        .on_click(window.listener_for(editor, {
+                            let buffer_id = for_excerpt.buffer_id;
+                            move |editor, e: &ClickEvent, window, cx| {
+                                if e.modifiers().alt {
+                                    editor.open_excerpts_common(
+                                        Some(jump_data.clone()),
+                                        e.modifiers().secondary(),
+                                        window,
+                                        cx,
+                                    );
+                                    return;
+                                }
+
+                                if is_folded {
+                                    editor.unfold_buffer(buffer_id, cx);
+                                } else {
+                                    editor.fold_buffer(buffer_id, cx);
+                                }
+                            }
+                        })),
+                ),
+        );
+
+    let file = for_excerpt.buffer.file().cloned();
+    let editor = editor.clone();
+
+    right_click_menu("buffer-header-context-menu")
+        .trigger(move |_, _, _| header)
+        .menu(move |window, cx| {
+            let menu_context = focus_handle.clone();
+            let editor = editor.clone();
+            let file = file.clone();
+            ContextMenu::build(window, cx, move |mut menu, window, cx| {
+                if let Some(file) = file
+                    && let Some(project) = editor.read(cx).project()
+                    && let Some(worktree) =
+                        project.read(cx).worktree_for_id(file.worktree_id(cx), cx)
+                {
+                    let path_style = file.path_style(cx);
+                    let worktree = worktree.read(cx);
+                    let relative_path = file.path();
+                    let entry_for_path = worktree.entry_for_path(relative_path);
+                    let abs_path = entry_for_path.map(|e| {
+                        e.canonical_path
+                            .as_deref()
+                            .map_or_else(|| worktree.absolutize(relative_path), Path::to_path_buf)
+                    });
+                    let has_relative_path = worktree.root_entry().is_some_and(Entry::is_dir);
+
+                    let parent_abs_path = abs_path
+                        .as_ref()
+                        .and_then(|abs_path| Some(abs_path.parent()?.to_path_buf()));
+                    let relative_path = has_relative_path
+                        .then_some(relative_path)
+                        .map(ToOwned::to_owned);
+
+                    let visible_in_project_panel = relative_path.is_some() && worktree.is_visible();
+                    let reveal_in_project_panel = entry_for_path
+                        .filter(|_| visible_in_project_panel)
+                        .map(|entry| entry.id);
+                    menu = menu
+                        .when_some(abs_path, |menu, abs_path| {
+                            menu.entry(
+                                "Copy Path",
+                                Some(Box::new(zed_actions::workspace::CopyPath)),
+                                window.handler_for(&editor, move |_, _, cx| {
+                                    cx.write_to_clipboard(ClipboardItem::new_string(
+                                        abs_path.to_string_lossy().into_owned(),
+                                    ));
+                                }),
+                            )
+                        })
+                        .when_some(relative_path, |menu, relative_path| {
+                            menu.entry(
+                                "Copy Relative Path",
+                                Some(Box::new(zed_actions::workspace::CopyRelativePath)),
+                                window.handler_for(&editor, move |_, _, cx| {
+                                    cx.write_to_clipboard(ClipboardItem::new_string(
+                                        relative_path.display(path_style).to_string(),
+                                    ));
+                                }),
+                            )
+                        })
+                        .when(
+                            reveal_in_project_panel.is_some() || parent_abs_path.is_some(),
+                            |menu| menu.separator(),
+                        )
+                        .when_some(reveal_in_project_panel, |menu, entry_id| {
+                            menu.entry(
+                                "Reveal In Project Panel",
+                                Some(Box::new(RevealInProjectPanel::default())),
+                                window.handler_for(&editor, move |editor, _, cx| {
+                                    if let Some(project) = &mut editor.project {
+                                        project.update(cx, |_, cx| {
+                                            cx.emit(project::Event::RevealInProjectPanel(entry_id))
+                                        });
+                                    }
+                                }),
+                            )
+                        })
+                        .when_some(parent_abs_path, |menu, parent_abs_path| {
+                            menu.entry(
+                                "Open in Terminal",
+                                Some(Box::new(OpenInTerminal)),
+                                window.handler_for(&editor, move |_, window, cx| {
+                                    window.dispatch_action(
+                                        OpenTerminal {
+                                            working_directory: parent_abs_path.clone(),
+                                            local: false,
+                                        }
+                                        .boxed_clone(),
+                                        cx,
+                                    );
+                                }),
+                            )
+                        });
+                }
+
+                menu.context(menu_context)
+            })
+        })
+}
+
 pub struct AcceptEditPredictionBinding(pub(crate) Option<gpui::KeyBinding>);
 
 impl AcceptEditPredictionBinding {

crates/editor/src/split_editor_view.rs 🔗

@@ -1,33 +1,26 @@
-use std::{cmp, collections::HashMap, path, path::Path};
+use std::cmp;
 
-use collections::HashSet;
-use file_icons::FileIcons;
-use git::status::FileStatus;
+use collections::{HashMap, HashSet};
 use gpui::{
-    AbsoluteLength, Action, AnyElement, App, AvailableSpace, Bounds, ClickEvent, ClipboardItem,
-    Context, DragMoveEvent, Element, Entity, Focusable, GlobalElementId, Hsla, InspectorElementId,
-    IntoElement, LayoutId, Length, Modifiers, MouseButton, ParentElement, Pixels,
-    StatefulInteractiveElement, Styled, TextStyleRefinement, Window, div, linear_color_stop,
-    linear_gradient, point, px, size,
+    AbsoluteLength, AnyElement, App, AvailableSpace, Bounds, Context, DragMoveEvent, Element,
+    Entity, GlobalElementId, Hsla, InspectorElementId, IntoElement, LayoutId, Length,
+    ParentElement, Pixels, StatefulInteractiveElement, Styled, TextStyleRefinement, Window, div,
+    linear_color_stop, linear_gradient, point, px, size,
 };
-use multi_buffer::{Anchor, ExcerptId, ExcerptInfo};
-use project::Entry;
+use multi_buffer::{Anchor, ExcerptId};
 use settings::Settings;
 use text::BufferId;
 use theme::ActiveTheme;
 use ui::scrollbars::ShowScrollbar;
-use ui::{
-    Button, ButtonLike, ButtonStyle, ContextMenu, Icon, IconName, Indicator, KeyBinding, Label,
-    Tooltip, h_flex, prelude::*, right_click_menu, text_for_keystroke, v_flex,
-};
-use workspace::{ItemSettings, OpenInTerminal, OpenTerminal, RevealInProjectPanel};
+use ui::{h_flex, prelude::*, v_flex};
+
+use gpui::ContentMask;
 
 use crate::{
-    DisplayRow, Editor, EditorSettings, EditorSnapshot, EditorStyle, FILE_HEADER_HEIGHT, JumpData,
-    MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, OpenExcerpts, RowExt, StickyHeaderExcerpt, ToggleFold,
-    ToggleFoldAll,
+    DisplayRow, Editor, EditorSettings, EditorSnapshot, EditorStyle, FILE_HEADER_HEIGHT,
+    MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, RowExt, StickyHeaderExcerpt,
     display_map::Block,
-    element::{EditorElement, SplitSide},
+    element::{EditorElement, SplitSide, header_jump_data, render_buffer_header},
     scroll::ScrollOffset,
     split::SplittableEditor,
 };
@@ -319,7 +312,7 @@ impl Element for SplitBufferHeadersElement {
         &mut self,
         _id: Option<&GlobalElementId>,
         _inspector_id: Option<&InspectorElementId>,
-        _bounds: Bounds<Pixels>,
+        bounds: Bounds<Pixels>,
         _request_layout: &mut Self::RequestLayoutState,
         prepaint: &mut Self::PrepaintState,
         window: &mut Window,
@@ -334,13 +327,15 @@ impl Element for SplitBufferHeadersElement {
 
         window.with_rem_size(rem_size, |window| {
             window.with_text_style(Some(text_style), |window| {
-                for header_layout in &mut prepaint.non_sticky_headers {
-                    header_layout.element.paint(window, cx);
-                }
+                window.with_content_mask(Some(ContentMask { bounds }), |window| {
+                    for header_layout in &mut prepaint.non_sticky_headers {
+                        header_layout.element.paint(window, cx);
+                    }
 
-                if let Some(mut sticky_header) = prepaint.sticky_header.take() {
-                    sticky_header.paint(window, cx);
-                }
+                    if let Some(mut sticky_header) = prepaint.sticky_header.take() {
+                        sticky_header.paint(window, cx);
+                    }
+                });
             });
         });
     }
@@ -532,8 +527,17 @@ impl SplitBufferHeadersElement {
                     .top_0(),
             )
             .child(
-                self.render_buffer_header(excerpt, false, selected, true, jump_data, window, cx)
-                    .into_any_element(),
+                render_buffer_header(
+                    &self.editor,
+                    excerpt,
+                    false,
+                    selected,
+                    true,
+                    jump_data,
+                    window,
+                    cx,
+                )
+                .into_any_element(),
             )
             .into_any_element();
 
@@ -606,9 +610,17 @@ impl SplitBufferHeadersElement {
                 latest_selection_anchors,
             );
 
-            let mut header = self
-                .render_buffer_header(excerpt, is_folded, selected, false, jump_data, window, cx)
-                .into_any_element();
+            let mut header = render_buffer_header(
+                &self.editor,
+                excerpt,
+                is_folded,
+                selected,
+                false,
+                jump_data,
+                window,
+                cx,
+            )
+            .into_any_element();
 
             let y_offset = (block_row.0 as f64 - scroll_position.y) * f64::from(line_height);
             let origin = point(bounds.origin.x, bounds.origin.y + Pixels::from(y_offset));
@@ -625,462 +637,4 @@ impl SplitBufferHeadersElement {
 
         headers
     }
-
-    fn render_buffer_header(
-        &self,
-        for_excerpt: &ExcerptInfo,
-        is_folded: bool,
-        is_selected: bool,
-        is_sticky: bool,
-        jump_data: JumpData,
-        window: &mut Window,
-        cx: &mut App,
-    ) -> impl IntoElement {
-        let editor = self.editor.read(cx);
-        let multi_buffer = editor.buffer.read(cx);
-        let is_read_only = self.editor.read(cx).read_only(cx);
-
-        let file_status = multi_buffer
-            .all_diff_hunks_expanded()
-            .then(|| editor.status_for_buffer_id(for_excerpt.buffer_id, cx))
-            .flatten();
-        let indicator = multi_buffer
-            .buffer(for_excerpt.buffer_id)
-            .and_then(|buffer| {
-                let buffer = buffer.read(cx);
-                let indicator_color = match (buffer.has_conflict(), buffer.is_dirty()) {
-                    (true, _) => Some(Color::Warning),
-                    (_, true) => Some(Color::Accent),
-                    (false, false) => None,
-                };
-                indicator_color.map(|indicator_color| Indicator::dot().color(indicator_color))
-            });
-
-        let include_root = editor
-            .project
-            .as_ref()
-            .map(|project| project.read(cx).visible_worktrees(cx).count() > 1)
-            .unwrap_or_default();
-        let file = for_excerpt.buffer.file();
-        let can_open_excerpts = file.is_none_or(|file| file.can_open());
-        let path_style = file.map(|file| file.path_style(cx));
-        let relative_path = for_excerpt.buffer.resolve_file_path(include_root, cx);
-        let (parent_path, filename) = if let Some(path) = &relative_path {
-            if let Some(path_style) = path_style {
-                let (dir, file_name) = path_style.split(path);
-                (dir.map(|dir| dir.to_owned()), Some(file_name.to_owned()))
-            } else {
-                (None, Some(path.clone()))
-            }
-        } else {
-            (None, None)
-        };
-        let focus_handle = self.editor.read(cx).focus_handle(cx);
-        let colors = cx.theme().colors();
-
-        let header = div()
-            .p_1()
-            .w_full()
-            .h(FILE_HEADER_HEIGHT as f32 * window.line_height())
-            .child(
-                h_flex()
-                    .size_full()
-                    .flex_basis(Length::Definite(DefiniteLength::Fraction(0.667)))
-                    .pl_1()
-                    .pr_2()
-                    .rounded_sm()
-                    .gap_1p5()
-                    .when(is_sticky, |el| el.shadow_md())
-                    .border_1()
-                    .map(|border| {
-                        let border_color = if !is_sticky
-                            && is_selected
-                            && is_folded
-                            && focus_handle.contains_focused(window, cx)
-                        {
-                            colors.border_focused
-                        } else {
-                            colors.border
-                        };
-                        border.border_color(border_color)
-                    })
-                    .bg(colors.editor_subheader_background)
-                    .hover(|style| style.bg(colors.element_hover))
-                    .map(|header| {
-                        let editor = self.editor.clone();
-                        let buffer_id = for_excerpt.buffer_id;
-                        let toggle_chevron_icon =
-                            FileIcons::get_chevron_icon(!is_folded, cx).map(Icon::from_path);
-                        let button_size = rems_from_px(28.);
-
-                        header.child(
-                            div()
-                                .hover(|style| style.bg(colors.element_selected))
-                                .rounded_xs()
-                                .child(
-                                    ButtonLike::new("toggle-buffer-fold")
-                                        .style(ButtonStyle::Transparent)
-                                        .height(button_size.into())
-                                        .width(button_size)
-                                        .children(toggle_chevron_icon)
-                                        .tooltip({
-                                            let focus_handle = focus_handle.clone();
-                                            let is_folded_for_tooltip = is_folded;
-                                            move |_window, cx| {
-                                                Tooltip::with_meta_in(
-                                                    if is_folded_for_tooltip {
-                                                        "Unfold Excerpt"
-                                                    } else {
-                                                        "Fold Excerpt"
-                                                    },
-                                                    Some(&ToggleFold),
-                                                    format!(
-                                                        "{} to toggle all",
-                                                        text_for_keystroke(
-                                                            &Modifiers::alt(),
-                                                            "click",
-                                                            cx
-                                                        )
-                                                    ),
-                                                    &focus_handle,
-                                                    cx,
-                                                )
-                                            }
-                                        })
-                                        .on_click(move |event, window, cx| {
-                                            if event.modifiers().alt {
-                                                editor.update(cx, |editor, cx| {
-                                                    editor.toggle_fold_all(
-                                                        &ToggleFoldAll,
-                                                        window,
-                                                        cx,
-                                                    );
-                                                });
-                                            } else {
-                                                if is_folded {
-                                                    editor.update(cx, |editor, cx| {
-                                                        editor.unfold_buffer(buffer_id, cx);
-                                                    });
-                                                } else {
-                                                    editor.update(cx, |editor, cx| {
-                                                        editor.fold_buffer(buffer_id, cx);
-                                                    });
-                                                }
-                                            }
-                                        }),
-                                ),
-                        )
-                    })
-                    .children(
-                        editor
-                            .addons
-                            .values()
-                            .filter_map(|addon| {
-                                addon.render_buffer_header_controls(for_excerpt, window, cx)
-                            })
-                            .take(1),
-                    )
-                    .when(!is_read_only, |this| {
-                        this.child(
-                            h_flex()
-                                .size_3()
-                                .justify_center()
-                                .flex_shrink_0()
-                                .children(indicator),
-                        )
-                    })
-                    .child(
-                        h_flex()
-                            .cursor_pointer()
-                            .id("path_header_block")
-                            .min_w_0()
-                            .size_full()
-                            .justify_between()
-                            .overflow_hidden()
-                            .child(h_flex().min_w_0().flex_1().gap_0p5().map(|path_header| {
-                                let filename = filename
-                                    .map(SharedString::from)
-                                    .unwrap_or_else(|| "untitled".into());
-
-                                path_header
-                                    .when(ItemSettings::get_global(cx).file_icons, |el| {
-                                        let path = path::Path::new(filename.as_str());
-                                        let icon =
-                                            FileIcons::get_icon(path, cx).unwrap_or_default();
-
-                                        el.child(Icon::from_path(icon).color(Color::Muted))
-                                    })
-                                    .child(
-                                        ButtonLike::new("filename-button")
-                                            .child(
-                                                Label::new(filename)
-                                                    .single_line()
-                                                    .color(file_status_label_color(file_status))
-                                                    .when(
-                                                        file_status.is_some_and(|s| s.is_deleted()),
-                                                        |label| label.strikethrough(),
-                                                    ),
-                                            )
-                                            .on_click(window.listener_for(&self.editor, {
-                                                let jump_data = jump_data.clone();
-                                                move |editor, e: &ClickEvent, window, cx| {
-                                                    editor.open_excerpts_common(
-                                                        Some(jump_data.clone()),
-                                                        e.modifiers().secondary(),
-                                                        window,
-                                                        cx,
-                                                    );
-                                                }
-                                            })),
-                                    )
-                                    .when(!for_excerpt.buffer.capability.editable(), |el| {
-                                        el.child(Icon::new(IconName::FileLock).color(Color::Muted))
-                                    })
-                                    .when_some(parent_path, |then, path| {
-                                        then.child(Label::new(path).truncate().color(
-                                            if file_status.is_some_and(FileStatus::is_deleted) {
-                                                Color::Custom(colors.text_disabled)
-                                            } else {
-                                                Color::Custom(colors.text_muted)
-                                            },
-                                        ))
-                                    })
-                            }))
-                            .when(
-                                can_open_excerpts && is_selected && relative_path.is_some(),
-                                |el| {
-                                    el.child(
-                                        Button::new("open-file-button", "Open File")
-                                            .style(ButtonStyle::OutlinedGhost)
-                                            .key_binding(KeyBinding::for_action_in(
-                                                &OpenExcerpts,
-                                                &focus_handle,
-                                                cx,
-                                            ))
-                                            .on_click(window.listener_for(&self.editor, {
-                                                let jump_data = jump_data.clone();
-                                                move |editor, e: &ClickEvent, window, cx| {
-                                                    editor.open_excerpts_common(
-                                                        Some(jump_data.clone()),
-                                                        e.modifiers().secondary(),
-                                                        window,
-                                                        cx,
-                                                    );
-                                                }
-                                            })),
-                                    )
-                                },
-                            )
-                            .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
-                            .on_click(window.listener_for(&self.editor, {
-                                let buffer_id = for_excerpt.buffer_id;
-                                move |editor, e: &ClickEvent, window, cx| {
-                                    if e.modifiers().alt {
-                                        editor.open_excerpts_common(
-                                            Some(jump_data.clone()),
-                                            e.modifiers().secondary(),
-                                            window,
-                                            cx,
-                                        );
-                                        return;
-                                    }
-
-                                    if is_folded {
-                                        editor.unfold_buffer(buffer_id, cx);
-                                    } else {
-                                        editor.fold_buffer(buffer_id, cx);
-                                    }
-                                }
-                            })),
-                    ),
-            );
-
-        let file = for_excerpt.buffer.file().cloned();
-        let editor = self.editor.clone();
-
-        right_click_menu("buffer-header-context-menu")
-            .trigger(move |_, _, _| header)
-            .menu(move |window, cx| {
-                let menu_context = focus_handle.clone();
-                let editor = editor.clone();
-                let file = file.clone();
-                ContextMenu::build(window, cx, move |mut menu, window, cx| {
-                    if let Some(file) = file
-                        && let Some(project) = editor.read(cx).project()
-                        && let Some(worktree) =
-                            project.read(cx).worktree_for_id(file.worktree_id(cx), cx)
-                    {
-                        let path_style = file.path_style(cx);
-                        let worktree = worktree.read(cx);
-                        let relative_path = file.path();
-                        let entry_for_path = worktree.entry_for_path(relative_path);
-                        let abs_path = entry_for_path.map(|e| {
-                            e.canonical_path.as_deref().map_or_else(
-                                || worktree.absolutize(relative_path),
-                                Path::to_path_buf,
-                            )
-                        });
-                        let has_relative_path = worktree.root_entry().is_some_and(Entry::is_dir);
-
-                        let parent_abs_path = abs_path
-                            .as_ref()
-                            .and_then(|abs_path| Some(abs_path.parent()?.to_path_buf()));
-                        let relative_path = has_relative_path
-                            .then_some(relative_path)
-                            .map(ToOwned::to_owned);
-
-                        let visible_in_project_panel =
-                            relative_path.is_some() && worktree.is_visible();
-                        let reveal_in_project_panel = entry_for_path
-                            .filter(|_| visible_in_project_panel)
-                            .map(|entry| entry.id);
-                        menu = menu
-                            .when_some(abs_path, |menu, abs_path| {
-                                menu.entry(
-                                    "Copy Path",
-                                    Some(Box::new(zed_actions::workspace::CopyPath)),
-                                    window.handler_for(&editor, move |_, _, cx| {
-                                        cx.write_to_clipboard(ClipboardItem::new_string(
-                                            abs_path.to_string_lossy().into_owned(),
-                                        ));
-                                    }),
-                                )
-                            })
-                            .when_some(relative_path, |menu, relative_path| {
-                                menu.entry(
-                                    "Copy Relative Path",
-                                    Some(Box::new(zed_actions::workspace::CopyRelativePath)),
-                                    window.handler_for(&editor, move |_, _, cx| {
-                                        cx.write_to_clipboard(ClipboardItem::new_string(
-                                            relative_path.display(path_style).to_string(),
-                                        ));
-                                    }),
-                                )
-                            })
-                            .when(
-                                reveal_in_project_panel.is_some() || parent_abs_path.is_some(),
-                                |menu| menu.separator(),
-                            )
-                            .when_some(reveal_in_project_panel, |menu, entry_id| {
-                                menu.entry(
-                                    "Reveal In Project Panel",
-                                    Some(Box::new(RevealInProjectPanel::default())),
-                                    window.handler_for(&editor, move |editor, _, cx| {
-                                        if let Some(project) = &mut editor.project {
-                                            project.update(cx, |_, cx| {
-                                                cx.emit(project::Event::RevealInProjectPanel(
-                                                    entry_id,
-                                                ))
-                                            });
-                                        }
-                                    }),
-                                )
-                            })
-                            .when_some(parent_abs_path, |menu, parent_abs_path| {
-                                menu.entry(
-                                    "Open in Terminal",
-                                    Some(Box::new(OpenInTerminal)),
-                                    window.handler_for(&editor, move |_, window, cx| {
-                                        window.dispatch_action(
-                                            OpenTerminal {
-                                                working_directory: parent_abs_path.clone(),
-                                                local: false,
-                                            }
-                                            .boxed_clone(),
-                                            cx,
-                                        );
-                                    }),
-                                )
-                            });
-                    }
-
-                    menu.context(menu_context)
-                })
-            })
-    }
-}
-
-fn header_jump_data(
-    editor_snapshot: &EditorSnapshot,
-    block_row_start: DisplayRow,
-    height: u32,
-    first_excerpt: &ExcerptInfo,
-    latest_selection_anchors: &HashMap<BufferId, Anchor>,
-) -> JumpData {
-    let jump_target = if let Some(anchor) = latest_selection_anchors.get(&first_excerpt.buffer_id)
-        && let Some(range) = editor_snapshot.context_range_for_excerpt(anchor.excerpt_id)
-        && let Some(buffer) = editor_snapshot
-            .buffer_snapshot()
-            .buffer_for_excerpt(anchor.excerpt_id)
-    {
-        JumpTargetInExcerptInput {
-            id: anchor.excerpt_id,
-            buffer,
-            excerpt_start_anchor: range.start,
-            jump_anchor: anchor.text_anchor,
-        }
-    } else {
-        JumpTargetInExcerptInput {
-            id: first_excerpt.id,
-            buffer: &first_excerpt.buffer,
-            excerpt_start_anchor: first_excerpt.range.context.start,
-            jump_anchor: first_excerpt.range.primary.start,
-        }
-    };
-    header_jump_data_inner(editor_snapshot, block_row_start, height, &jump_target)
-}
-
-struct JumpTargetInExcerptInput<'a> {
-    id: ExcerptId,
-    buffer: &'a language::BufferSnapshot,
-    excerpt_start_anchor: text::Anchor,
-    jump_anchor: text::Anchor,
-}
-
-fn header_jump_data_inner(
-    snapshot: &EditorSnapshot,
-    block_row_start: DisplayRow,
-    height: u32,
-    for_excerpt: &JumpTargetInExcerptInput,
-) -> JumpData {
-    let buffer = &for_excerpt.buffer;
-    let jump_position = language::ToPoint::to_point(&for_excerpt.jump_anchor, buffer);
-    let excerpt_start = for_excerpt.excerpt_start_anchor;
-    let rows_from_excerpt_start = if for_excerpt.jump_anchor == excerpt_start {
-        0
-    } else {
-        let excerpt_start_point = language::ToPoint::to_point(&excerpt_start, buffer);
-        jump_position.row.saturating_sub(excerpt_start_point.row)
-    };
-
-    let line_offset_from_top = (block_row_start.0 + height + rows_from_excerpt_start)
-        .saturating_sub(
-            snapshot
-                .scroll_anchor
-                .scroll_position(&snapshot.display_snapshot)
-                .y as u32,
-        );
-
-    JumpData::MultiBufferPoint {
-        excerpt_id: for_excerpt.id,
-        anchor: for_excerpt.jump_anchor,
-        position: jump_position,
-        line_offset_from_top,
-    }
-}
-
-fn file_status_label_color(file_status: Option<FileStatus>) -> Color {
-    file_status.map_or(Color::Default, |status| {
-        if status.is_conflicted() {
-            Color::Conflict
-        } else if status.is_modified() {
-            Color::Modified
-        } else if status.is_deleted() {
-            Color::Disabled
-        } else if status.is_created() {
-            Color::Created
-        } else {
-            Color::Default
-        }
-    })
 }