Persist the default Git diff layout
This commit is contained in:
22
src/app.rs
22
src/app.rs
@@ -8,14 +8,15 @@ mod view;
|
|||||||
pub(crate) use view::app_theme;
|
pub(crate) use view::app_theme;
|
||||||
|
|
||||||
use generation::ChatMessage;
|
use generation::ChatMessage;
|
||||||
use git::{ActiveGitOperation, GitDiff, GitDiffMode, GitWorktree};
|
use git::{ActiveGitOperation, GitDiff, GitWorktree};
|
||||||
use model_manager::{ActiveDownload, ModelDownload, ModelOperation};
|
use model_manager::{ActiveDownload, ModelDownload, ModelOperation};
|
||||||
use preferences::PreferenceDraft;
|
use preferences::PreferenceDraft;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use preferences::{parse_optional_gib, parse_streaming_cache};
|
use preferences::{parse_optional_gib, parse_streaming_cache};
|
||||||
|
|
||||||
use crate::config::{
|
use crate::config::{
|
||||||
Config, DevBrainConfig, EndpointConfig, GitConfig, GitDiffAlgorithm, GitDiffWhitespace,
|
Config, DevBrainConfig, EndpointConfig, GitConfig, GitDiffAlgorithm, GitDiffLayout,
|
||||||
|
GitDiffWhitespace,
|
||||||
};
|
};
|
||||||
use crate::database::{Database, ProjectWithSessions, SessionState, StoredMessage};
|
use crate::database::{Database, ProjectWithSessions, SessionState, StoredMessage};
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
@@ -77,7 +78,7 @@ pub(crate) struct App {
|
|||||||
git_selected_files: HashSet<PathBuf>,
|
git_selected_files: HashSet<PathBuf>,
|
||||||
git_commit_message: String,
|
git_commit_message: String,
|
||||||
git_diff: Option<GitDiff>,
|
git_diff: Option<GitDiff>,
|
||||||
git_diff_mode: GitDiffMode,
|
git_diff_layout: GitDiffLayout,
|
||||||
git_commit_all_confirmation: bool,
|
git_commit_all_confirmation: bool,
|
||||||
git_operation: Option<ActiveGitOperation>,
|
git_operation: Option<ActiveGitOperation>,
|
||||||
last_git_scan: Instant,
|
last_git_scan: Instant,
|
||||||
@@ -350,6 +351,7 @@ pub(crate) enum Message {
|
|||||||
PreferenceEndpointCorsChanged(bool),
|
PreferenceEndpointCorsChanged(bool),
|
||||||
PreferenceDevBrainEnabledChanged(bool),
|
PreferenceDevBrainEnabledChanged(bool),
|
||||||
PreferenceDevBrainVaultChanged(String),
|
PreferenceDevBrainVaultChanged(String),
|
||||||
|
PreferenceGitDiffLayoutChanged(GitDiffLayout),
|
||||||
PreferenceGitDiffAlgorithmChanged(GitDiffAlgorithm),
|
PreferenceGitDiffAlgorithmChanged(GitDiffAlgorithm),
|
||||||
PreferenceGitContextLinesChanged(String),
|
PreferenceGitContextLinesChanged(String),
|
||||||
PreferenceGitInterhunkLinesChanged(String),
|
PreferenceGitInterhunkLinesChanged(String),
|
||||||
@@ -437,7 +439,7 @@ pub(crate) enum Message {
|
|||||||
SwitchGitBranch(String),
|
SwitchGitBranch(String),
|
||||||
ToggleGitFile(PathBuf),
|
ToggleGitFile(PathBuf),
|
||||||
OpenGitDiff(PathBuf),
|
OpenGitDiff(PathBuf),
|
||||||
SetGitDiffMode(GitDiffMode),
|
SetGitDiffLayout(GitDiffLayout),
|
||||||
GitDiffScrolled(scrollable::Viewport),
|
GitDiffScrolled(scrollable::Viewport),
|
||||||
GitCommitMessageChanged(String),
|
GitCommitMessageChanged(String),
|
||||||
GitStageSelected,
|
GitStageSelected,
|
||||||
@@ -503,6 +505,7 @@ impl App {
|
|||||||
let metrics =
|
let metrics =
|
||||||
Arc::new(Metrics::new(&application_support_path().join("kv-cache")));
|
Arc::new(Metrics::new(&application_support_path().join("kv-cache")));
|
||||||
let metrics_snapshot = metrics.snapshot();
|
let metrics_snapshot = metrics.snapshot();
|
||||||
|
let git_diff_layout = config.git.diff_layout;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
let (runtime_config, generation_service, endpoint, service_error) =
|
let (runtime_config, generation_service, endpoint, service_error) =
|
||||||
spawn_services(&config, Arc::clone(&metrics));
|
spawn_services(&config, Arc::clone(&metrics));
|
||||||
@@ -532,7 +535,7 @@ impl App {
|
|||||||
git_selected_files: HashSet::new(),
|
git_selected_files: HashSet::new(),
|
||||||
git_commit_message: String::new(),
|
git_commit_message: String::new(),
|
||||||
git_diff: None,
|
git_diff: None,
|
||||||
git_diff_mode: GitDiffMode::default(),
|
git_diff_layout,
|
||||||
git_commit_all_confirmation: false,
|
git_commit_all_confirmation: false,
|
||||||
git_operation: None,
|
git_operation: None,
|
||||||
last_git_scan: Instant::now() - GIT_SCAN_INTERVAL,
|
last_git_scan: Instant::now() - GIT_SCAN_INTERVAL,
|
||||||
@@ -641,6 +644,7 @@ impl App {
|
|||||||
let context_limit = config.generation.context_tokens.max(0) as u32;
|
let context_limit = config.generation.context_tokens.max(0) as u32;
|
||||||
let metrics = Arc::new(Metrics::new(&application_support_path().join("kv-cache")));
|
let metrics = Arc::new(Metrics::new(&application_support_path().join("kv-cache")));
|
||||||
let metrics_snapshot = metrics.snapshot();
|
let metrics_snapshot = metrics.snapshot();
|
||||||
|
let git_diff_layout = config.git.diff_layout;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
let (runtime_config, generation_service, endpoint, service_error) =
|
let (runtime_config, generation_service, endpoint, service_error) =
|
||||||
spawn_services(&config, Arc::clone(&metrics));
|
spawn_services(&config, Arc::clone(&metrics));
|
||||||
@@ -674,7 +678,7 @@ impl App {
|
|||||||
git_selected_files: HashSet::new(),
|
git_selected_files: HashSet::new(),
|
||||||
git_commit_message: String::new(),
|
git_commit_message: String::new(),
|
||||||
git_diff: None,
|
git_diff: None,
|
||||||
git_diff_mode: GitDiffMode::default(),
|
git_diff_layout,
|
||||||
git_commit_all_confirmation: false,
|
git_commit_all_confirmation: false,
|
||||||
git_operation: None,
|
git_operation: None,
|
||||||
last_git_scan: Instant::now() - GIT_SCAN_INTERVAL,
|
last_git_scan: Instant::now() - GIT_SCAN_INTERVAL,
|
||||||
@@ -1187,6 +1191,10 @@ impl App {
|
|||||||
self.preference_draft.dev_brain_vault_path = value;
|
self.preference_draft.dev_brain_vault_path = value;
|
||||||
self.preference_error = None;
|
self.preference_error = None;
|
||||||
}
|
}
|
||||||
|
Message::PreferenceGitDiffLayoutChanged(layout) => {
|
||||||
|
self.preference_draft.git_diff_layout = layout;
|
||||||
|
self.preference_error = None;
|
||||||
|
}
|
||||||
Message::PreferenceGitDiffAlgorithmChanged(algorithm) => {
|
Message::PreferenceGitDiffAlgorithmChanged(algorithm) => {
|
||||||
self.preference_draft.git_diff_algorithm = algorithm;
|
self.preference_draft.git_diff_algorithm = algorithm;
|
||||||
self.preference_error = None;
|
self.preference_error = None;
|
||||||
@@ -1798,7 +1806,7 @@ impl App {
|
|||||||
Message::SwitchGitBranch(branch) => self.switch_git_branch(&branch),
|
Message::SwitchGitBranch(branch) => self.switch_git_branch(&branch),
|
||||||
Message::ToggleGitFile(path) => self.toggle_git_file(path),
|
Message::ToggleGitFile(path) => self.toggle_git_file(path),
|
||||||
Message::OpenGitDiff(path) => self.open_git_diff(&path),
|
Message::OpenGitDiff(path) => self.open_git_diff(&path),
|
||||||
Message::SetGitDiffMode(mode) => self.git_diff_mode = mode,
|
Message::SetGitDiffLayout(layout) => self.git_diff_layout = layout,
|
||||||
Message::GitDiffScrolled(viewport) => {
|
Message::GitDiffScrolled(viewport) => {
|
||||||
let offset = scrollable::AbsoluteOffset {
|
let offset = scrollable::AbsoluteOffset {
|
||||||
x: viewport.absolute_offset().x,
|
x: viewport.absolute_offset().x,
|
||||||
|
|||||||
@@ -40,13 +40,6 @@ pub(super) struct GitWorktree {
|
|||||||
pub(super) files: Vec<GitFile>,
|
pub(super) files: Vec<GitFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
|
||||||
pub(crate) enum GitDiffMode {
|
|
||||||
#[default]
|
|
||||||
Unified,
|
|
||||||
Split,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub(super) enum GitDiffLineKind {
|
pub(super) enum GitDiffLineKind {
|
||||||
Section,
|
Section,
|
||||||
@@ -186,6 +179,7 @@ impl App {
|
|||||||
match load_diff(&worktree.root, file, &self.config.git) {
|
match load_diff(&worktree.root, file, &self.config.git) {
|
||||||
Ok(diff) => {
|
Ok(diff) => {
|
||||||
self.git_diff = Some(diff);
|
self.git_diff = Some(diff);
|
||||||
|
self.git_diff_layout = self.config.git.diff_layout;
|
||||||
self.error = None;
|
self.error = None;
|
||||||
}
|
}
|
||||||
Err(error) => self.error = Some(error),
|
Err(error) => self.error = Some(error),
|
||||||
@@ -1113,6 +1107,7 @@ mod tests {
|
|||||||
.find(|file| file.display_path == "changed.txt")
|
.find(|file| file.display_path == "changed.txt")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let settings = GitConfig {
|
let settings = GitConfig {
|
||||||
|
diff_layout: GitDiffLayout::Unified,
|
||||||
diff_algorithm: GitDiffAlgorithm::Patience,
|
diff_algorithm: GitDiffAlgorithm::Patience,
|
||||||
context_lines: 0,
|
context_lines: 0,
|
||||||
interhunk_lines: 0,
|
interhunk_lines: 0,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ pub(super) struct PreferenceDraft {
|
|||||||
pub(super) endpoint_cors: bool,
|
pub(super) endpoint_cors: bool,
|
||||||
pub(super) dev_brain_enabled: bool,
|
pub(super) dev_brain_enabled: bool,
|
||||||
pub(super) dev_brain_vault_path: String,
|
pub(super) dev_brain_vault_path: String,
|
||||||
|
pub(super) git_diff_layout: GitDiffLayout,
|
||||||
pub(super) git_diff_algorithm: GitDiffAlgorithm,
|
pub(super) git_diff_algorithm: GitDiffAlgorithm,
|
||||||
pub(super) git_context_lines: String,
|
pub(super) git_context_lines: String,
|
||||||
pub(super) git_interhunk_lines: String,
|
pub(super) git_interhunk_lines: String,
|
||||||
@@ -70,6 +71,7 @@ impl PreferenceDraft {
|
|||||||
endpoint_cors: config.endpoint.cors,
|
endpoint_cors: config.endpoint.cors,
|
||||||
dev_brain_enabled: config.dev_brain.enabled,
|
dev_brain_enabled: config.dev_brain.enabled,
|
||||||
dev_brain_vault_path: config.dev_brain.vault_path.clone().unwrap_or_default(),
|
dev_brain_vault_path: config.dev_brain.vault_path.clone().unwrap_or_default(),
|
||||||
|
git_diff_layout: config.git.diff_layout,
|
||||||
git_diff_algorithm: config.git.diff_algorithm,
|
git_diff_algorithm: config.git.diff_algorithm,
|
||||||
git_context_lines: config.git.context_lines.to_string(),
|
git_context_lines: config.git.context_lines.to_string(),
|
||||||
git_interhunk_lines: config.git.interhunk_lines.to_string(),
|
git_interhunk_lines: config.git.interhunk_lines.to_string(),
|
||||||
@@ -140,6 +142,7 @@ impl PreferenceDraft {
|
|||||||
|
|
||||||
pub(super) fn git(&self) -> Result<GitConfig, String> {
|
pub(super) fn git(&self) -> Result<GitConfig, String> {
|
||||||
Ok(GitConfig {
|
Ok(GitConfig {
|
||||||
|
diff_layout: self.git_diff_layout,
|
||||||
diff_algorithm: self.git_diff_algorithm,
|
diff_algorithm: self.git_diff_algorithm,
|
||||||
context_lines: parse_u32("Git diff context lines", &self.git_context_lines)?,
|
context_lines: parse_u32("Git diff context lines", &self.git_context_lines)?,
|
||||||
interhunk_lines: parse_u32("Git diff interhunk lines", &self.git_interhunk_lines)?,
|
interhunk_lines: parse_u32("Git diff interhunk lines", &self.git_interhunk_lines)?,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use super::{
|
|||||||
ModelDownload, ModelOperation, PreferenceSection, ProjectChoice, chat_scroll_id, composer_id,
|
ModelDownload, ModelOperation, PreferenceSection, ProjectChoice, chat_scroll_id, composer_id,
|
||||||
models_path, preferences_scroll_id,
|
models_path, preferences_scroll_id,
|
||||||
};
|
};
|
||||||
use crate::config::{GIT_DIFF_ALGORITHMS, GIT_DIFF_WHITESPACE_MODES};
|
use crate::config::{GIT_DIFF_ALGORITHMS, GIT_DIFF_LAYOUTS, GIT_DIFF_WHITESPACE_MODES};
|
||||||
use crate::database::{ProjectWithSessions, Session, SessionState};
|
use crate::database::{ProjectWithSessions, Session, SessionState};
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
self, DownloadPhase, MODEL_CHOICES, ManagedArtifact, ManagedArtifactState, ModelChoice,
|
self, DownloadPhase, MODEL_CHOICES, ManagedArtifact, ManagedArtifactState, ModelChoice,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::app::git::{GitChangeKind, GitDiffLine, GitDiffLineKind, GitDiffMode, GitDiffRow};
|
use crate::app::git::{GitChangeKind, GitDiffLine, GitDiffLineKind, GitDiffRow};
|
||||||
use crate::app::{git_diff_new_scroll_id, git_diff_old_scroll_id};
|
use crate::app::{git_diff_new_scroll_id, git_diff_old_scroll_id};
|
||||||
|
use crate::config::GitDiffLayout;
|
||||||
use iced::widget::column;
|
use iced::widget::column;
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
@@ -230,13 +231,13 @@ impl App {
|
|||||||
|
|
||||||
pub(super) fn git_diff_panel(&self) -> Element<'_, Message> {
|
pub(super) fn git_diff_panel(&self) -> Element<'_, Message> {
|
||||||
let diff = self.git_diff.as_ref().unwrap();
|
let diff = self.git_diff.as_ref().unwrap();
|
||||||
let unified_active = self.git_diff_mode == GitDiffMode::Unified;
|
let unified_active = self.git_diff_layout == GitDiffLayout::Unified;
|
||||||
let split_active = self.git_diff_mode == GitDiffMode::Split;
|
let split_active = self.git_diff_layout == GitDiffLayout::Split;
|
||||||
let mode = container(
|
let mode = container(
|
||||||
row![
|
row![
|
||||||
button(text("1 column").size(12))
|
button(text("1 column").size(12))
|
||||||
.padding([4, 10])
|
.padding([4, 10])
|
||||||
.on_press(Message::SetGitDiffMode(GitDiffMode::Unified))
|
.on_press(Message::SetGitDiffLayout(GitDiffLayout::Unified))
|
||||||
.style(move |theme, status| segmented_button_style(
|
.style(move |theme, status| segmented_button_style(
|
||||||
theme,
|
theme,
|
||||||
status,
|
status,
|
||||||
@@ -244,7 +245,7 @@ impl App {
|
|||||||
)),
|
)),
|
||||||
button(text("2 columns").size(12))
|
button(text("2 columns").size(12))
|
||||||
.padding([4, 10])
|
.padding([4, 10])
|
||||||
.on_press(Message::SetGitDiffMode(GitDiffMode::Split))
|
.on_press(Message::SetGitDiffLayout(GitDiffLayout::Split))
|
||||||
.style(move |theme, status| segmented_button_style(
|
.style(move |theme, status| segmented_button_style(
|
||||||
theme,
|
theme,
|
||||||
status,
|
status,
|
||||||
|
|||||||
@@ -199,6 +199,20 @@ impl App {
|
|||||||
PreferenceSection::Git,
|
PreferenceSection::Git,
|
||||||
"GIT DIFFS",
|
"GIT DIFFS",
|
||||||
column![
|
column![
|
||||||
|
row![
|
||||||
|
hint(
|
||||||
|
text("Default layout").size(13).width(Length::Fill),
|
||||||
|
"Layout used whenever a file diff is opened. The control in the diff can still change that one view.",
|
||||||
|
),
|
||||||
|
pick_list(
|
||||||
|
&GIT_DIFF_LAYOUTS[..],
|
||||||
|
Some(self.preference_draft.git_diff_layout),
|
||||||
|
Message::PreferenceGitDiffLayoutChanged,
|
||||||
|
)
|
||||||
|
.width(240),
|
||||||
|
]
|
||||||
|
.spacing(12)
|
||||||
|
.align_y(Alignment::Center),
|
||||||
row![
|
row![
|
||||||
hint(
|
hint(
|
||||||
text("Algorithm").size(13).width(Length::Fill),
|
text("Algorithm").size(13).width(Length::Fill),
|
||||||
|
|||||||
@@ -46,6 +46,25 @@ pub const GIT_DIFF_ALGORITHMS: [GitDiffAlgorithm; 3] = [
|
|||||||
GitDiffAlgorithm::Minimal,
|
GitDiffAlgorithm::Minimal,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
pub const GIT_DIFF_LAYOUTS: [GitDiffLayout; 2] = [GitDiffLayout::Unified, GitDiffLayout::Split];
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
pub enum GitDiffLayout {
|
||||||
|
#[default]
|
||||||
|
Unified,
|
||||||
|
Split,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for GitDiffLayout {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
formatter.write_str(match self {
|
||||||
|
Self::Unified => "1 column",
|
||||||
|
Self::Split => "2 columns",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
|
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub enum GitDiffAlgorithm {
|
pub enum GitDiffAlgorithm {
|
||||||
@@ -96,6 +115,7 @@ impl fmt::Display for GitDiffWhitespace {
|
|||||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[serde(default, deny_unknown_fields)]
|
#[serde(default, deny_unknown_fields)]
|
||||||
pub struct GitConfig {
|
pub struct GitConfig {
|
||||||
|
pub diff_layout: GitDiffLayout,
|
||||||
pub diff_algorithm: GitDiffAlgorithm,
|
pub diff_algorithm: GitDiffAlgorithm,
|
||||||
pub context_lines: u32,
|
pub context_lines: u32,
|
||||||
pub interhunk_lines: u32,
|
pub interhunk_lines: u32,
|
||||||
@@ -107,6 +127,7 @@ pub struct GitConfig {
|
|||||||
impl Default for GitConfig {
|
impl Default for GitConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
diff_layout: GitDiffLayout::Unified,
|
||||||
diff_algorithm: GitDiffAlgorithm::Default,
|
diff_algorithm: GitDiffAlgorithm::Default,
|
||||||
context_lines: 3,
|
context_lines: 3,
|
||||||
interhunk_lines: 0,
|
interhunk_lines: 0,
|
||||||
@@ -282,6 +303,7 @@ mod tests {
|
|||||||
..RuntimePreferences::default()
|
..RuntimePreferences::default()
|
||||||
},
|
},
|
||||||
git: GitConfig {
|
git: GitConfig {
|
||||||
|
diff_layout: GitDiffLayout::Split,
|
||||||
diff_algorithm: GitDiffAlgorithm::Patience,
|
diff_algorithm: GitDiffAlgorithm::Patience,
|
||||||
context_lines: 5,
|
context_lines: 5,
|
||||||
whitespace: GitDiffWhitespace::IgnoreEndOfLine,
|
whitespace: GitDiffWhitespace::IgnoreEndOfLine,
|
||||||
@@ -297,7 +319,7 @@ mod tests {
|
|||||||
"model: glm-5.2\na2ui_enabled: false\n\
|
"model: glm-5.2\na2ui_enabled: false\n\
|
||||||
generation:\n context_tokens: 65536\n reasoning_mode: none\n\
|
generation:\n context_tokens: 65536\n reasoning_mode: none\n\
|
||||||
runtime:\n ssd:\n enabled: true\n cache: 64GB\n\
|
runtime:\n ssd:\n enabled: true\n cache: 64GB\n\
|
||||||
git:\n diff_algorithm: patience\n context_lines: 5\n whitespace: ignore-end-of-line\n"
|
git:\n diff_layout: split\n diff_algorithm: patience\n context_lines: 5\n whitespace: ignore-end-of-line\n"
|
||||||
);
|
);
|
||||||
assert_eq!(Config::load(&path).unwrap(), config);
|
assert_eq!(Config::load(&path).unwrap(), config);
|
||||||
fs::remove_dir_all(&directory).unwrap();
|
fs::remove_dir_all(&directory).unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user