Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions assets/settings/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,11 @@
// Should the name or path be displayed first in the git view.
// "path_style": "file_name_first" or "file_path_first"
"path_style": "file_name_first",
// Whether the project diff view opens in stacked or side-by-side mode.
//
// Choices: stacked, side_by_side
// Default: stacked
"default_diff_view": "stacked",
},
// The list of custom Git hosting providers.
"git_hosting_providers": [
Expand Down
17 changes: 13 additions & 4 deletions crates/editor/src/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,16 +467,25 @@ impl SplittableEditor {
}

fn split(&mut self, _: &SplitDiff, window: &mut Window, cx: &mut Context<Self>) {
let Some(workspace) = self.workspace.upgrade() else {
return;
};
let project = workspace.read(cx).project().clone();
self.do_split(project, window, cx);
}

pub fn do_split(
&mut self,
project: Entity<Project>,
window: &mut Window,
cx: &mut Context<Self>,
) {
if !cx.has_flag::<SplitDiffFeatureFlag>() {
return;
}
if self.lhs.is_some() {
return;
}
let Some(workspace) = self.workspace.upgrade() else {
return;
};
let project = workspace.read(cx).project().clone();

let lhs_multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(Capability::ReadOnly);
Expand Down
80 changes: 78 additions & 2 deletions crates/git_ui/src/project_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ use gpui::{
};
use language::{Anchor, Buffer, Capability, OffsetRangeExt};
use multi_buffer::{MultiBuffer, PathKey};
use project::project_settings::ProjectSettings;
use project::{
Project, ProjectPath,
git_store::{
Repository,
branch_diff::{self, BranchDiffEvent, DiffBase},
},
};
use settings::{Settings, SettingsStore};
use settings::{DefaultDiffView, Settings, SettingsStore};
use smol::future::yield_now;
use std::any::{Any, TypeId};
use std::sync::Arc;
Expand Down Expand Up @@ -300,7 +301,7 @@ impl ProjectDiff {
});

let editor = cx.new(|cx| {
let diff_display_editor = SplittableEditor::new_unsplit(
let mut diff_display_editor = SplittableEditor::new_unsplit(
multibuffer.clone(),
project.clone(),
workspace.clone(),
Expand Down Expand Up @@ -332,6 +333,12 @@ impl ProjectDiff {
}
}
});

if ProjectSettings::get_global(cx).git.default_diff_view == DefaultDiffView::SideBySide
{
diff_display_editor.do_split(project.clone(), window, cx);
}

diff_display_editor
});
let editor_subscription = cx.subscribe_in(&editor, window, Self::handle_editor_event);
Expand Down Expand Up @@ -2727,4 +2734,73 @@ mod tests {
assert_eq!(paths_b.len(), 1);
assert_eq!(*paths_b[0], *"b.txt");
}

#[gpui::test]
async fn test_default_diff_view_is_stacked_when_no_setting_specified(cx: &mut TestAppContext) {
init_test(cx);
assert_default_diff_view(None, false, cx).await;
}

#[gpui::test]
async fn test_default_diff_view_is_stacked_when_set_to_stacked(cx: &mut TestAppContext) {
init_test(cx);
assert_default_diff_view(Some(settings::DefaultDiffView::Stacked), false, cx).await;
}

#[gpui::test]
async fn test_default_diff_view_is_split_when_set_to_side_by_side(cx: &mut TestAppContext) {
init_test(cx);
assert_default_diff_view(Some(settings::DefaultDiffView::SideBySide), true, cx).await;
}

async fn assert_default_diff_view(
default_diff_view: Option<settings::DefaultDiffView>,
expect_split: bool,
cx: &mut TestAppContext,
) {
if let Some(default_diff_view) = default_diff_view {
cx.update(|cx| {
let mut settings = ProjectSettings::get_global(cx).clone();
settings.git.default_diff_view = default_diff_view;
ProjectSettings::override_global(settings, cx);
});
}

let fs = FakeFs::new(cx.executor());
fs.insert_tree(
path!("/project"),
json!({
".git": {},
"foo.txt": "dominate\n",
}),
)
.await;
let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;

fs.set_head_and_index_for_repo(
Path::new(path!("/project/.git")),
&[("foo.txt", "intimidate\n".to_string())],
);

let (workspace, cx) =
cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
cx.run_until_parked();

cx.focus(&workspace);
cx.update(|window, cx| {
window.dispatch_action(project_diff::Diff.boxed_clone(), cx);
});
cx.run_until_parked();

let diff_item = workspace.update(cx, |workspace, cx| {
workspace.active_item_as::<ProjectDiff>(cx).unwrap()
});
diff_item.read_with(cx, |diff, cx| {
assert_eq!(
diff.editor.read(cx).is_split(),
expect_split,
"Expected is_split() to be {expect_split}"
);
});
}
}
5 changes: 5 additions & 0 deletions crates/project/src/project_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,10 @@ pub struct GitSettings {
///
/// Default: file_name_first
pub path_style: GitPathStyle,
/// Whether the project diff view opens in stacked or side-by-side mode.
///
/// Default: stacked
pub default_diff_view: settings::DefaultDiffView,
}

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -643,6 +647,7 @@ impl Settings for ProjectSettings {
},
hunk_style: git.hunk_style.unwrap(),
path_style: git.path_style.unwrap().into(),
default_diff_view: git.default_diff_view.unwrap(),
};
Self {
context_servers: project
Expand Down
8 changes: 6 additions & 2 deletions crates/settings_content/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use settings_macros::{MergeFrom, with_fallible_options};
use util::serde::default_true;

use crate::{
AllLanguageSettingsContent, DelayMs, ExtendingVec, ParseStatus, ProjectTerminalSettingsContent,
RootUserSettings, SlashCommandSettings, fallible_options,
AllLanguageSettingsContent, DefaultDiffView, DelayMs, ExtendingVec, ParseStatus,
ProjectTerminalSettingsContent, RootUserSettings, SlashCommandSettings, fallible_options,
};

#[with_fallible_options]
Expand Down Expand Up @@ -468,6 +468,10 @@ pub struct GitSettings {
///
/// Default: file_name_first
pub path_style: Option<GitPathStyle>,
/// Whether the project diff view opens in stacked or side-by-side mode.
///
/// Default: stacked
pub default_diff_view: Option<DefaultDiffView>,
}

#[with_fallible_options]
Expand Down
23 changes: 23 additions & 0 deletions crates/settings_content/src/settings_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,29 @@ pub struct GitPanelSettingsContent {
pub tree_view: Option<bool>,
}

#[derive(
Default,
Copy,
Clone,
Debug,
Serialize,
Deserialize,
JsonSchema,
MergeFrom,
PartialEq,
Eq,
strum::VariantArray,
strum::VariantNames,
)]
#[serde(rename_all = "snake_case")]
pub enum DefaultDiffView {
/// Show the old and new content in a single editor, interleaved.
#[default]
Stacked,
/// Show the old and new content in side-by-side editors.
SideBySide,
}

#[derive(
Default,
Copy,
Expand Down
1 change: 1 addition & 0 deletions crates/settings_ui/src/settings_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ fn init_renderers(cx: &mut App) {
.add_basic_renderer::<settings::NotifyWhenAgentWaiting>(render_dropdown)
.add_basic_renderer::<settings::ImageFileSizeUnit>(render_dropdown)
.add_basic_renderer::<settings::StatusStyle>(render_dropdown)
.add_basic_renderer::<settings::DefaultDiffView>(render_dropdown)
.add_basic_renderer::<settings::EncodingDisplayOptions>(render_dropdown)
.add_basic_renderer::<settings::PaneSplitDirectionHorizontal>(render_dropdown)
.add_basic_renderer::<settings::PaneSplitDirectionVertical>(render_dropdown)
Expand Down