Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify theme overrides #1652

Merged
merged 4 commits into from
Jun 25, 2023
Merged
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Breaking Change
* `focus_XYZ` key bindings are merged into the `move_XYZ` set, so only one way to bind arrow-like keys from now on ([#1539](https://github.com/extrawurst/gitui/issues/1539))
* Do you use a custom theme?

The way themes work got changed and simplified ([see docs](https://github.com/extrawurst/gitui/blob/master/THEMES.md) for more info):

* The format of `theme.ron` has changed: you only specify the colors etc. that should differ from their default value
cruessler marked this conversation as resolved.
Show resolved Hide resolved
* Future additions of colors etc. will not break existing themes anymore

### Added
* allow reset (soft,mixed,hard) from commit log ([#1500](https://github.com/extrawurst/gitui/issues/1500))
Expand All @@ -41,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* allow `copy` file path on revision files and status tree [[@yanganto]](https://github.com/yanganto) ([#1516](https://github.com/extrawurst/gitui/pull/1516))
* print message of where log will be written if `-l` is set ([#1472](https://github.com/extrawurst/gitui/pull/1472))
* show remote branches in log [[@cruessler](https://github.com/cruessler)] ([#1501](https://github.com/extrawurst/gitui/issues/1501))
* simplify theme overrides [[@cruessler](https://github.com/cruessler)] ([#1367](https://github.com/extrawurst/gitui/issues/1367))

### Fixes
* fixed side effect of crossterm 0.26 on windows that caused double input of all keys [[@pm100]](https://github/pm100) ([#1686](https://github.com/extrawurst/gitui/pull/1686))
Expand Down
18 changes: 15 additions & 3 deletions THEMES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,27 @@
default on light terminal:
![](assets/light-theme.png)

to change the colors of the default theme you have to modify `theme.ron` file
[Ron format](https://github.com/ron-rs/ron) located at config path. The path differs depending on the operating system:
To change the colors of the default theme you need to add a `theme.ron` file that contains the colors you want to override. Note that you don’t have to specify the full theme anymore (as of 0.23). Instead, it is sufficient to override just the values that you want to differ from their default values.

The file uses the [Ron format](https://github.com/ron-rs/ron) and is located at one of the following paths, depending on your operating system:

* `$HOME/.config/gitui/theme.ron` (mac)
* `$XDG_CONFIG_HOME/gitui/theme.ron` (linux using XDG)
* `$HOME/.config/gitui/theme.ron` (linux)
* `%APPDATA%/gitui/theme.ron` (Windows)

Alternatively you may make a theme in the same directory mentioned above with and select with the `-t` flag followed by the name of the file in the directory. E.g. If you are on linux calling `gitui -t arc.ron` wil use `$XDG_CONFIG_HOME/gitui/arc.ron` or `$HOME/.config/gitui/arc.ron`
Alternatively, you can create a theme in the same directory mentioned above and use it with the `-t` flag followed by the name of the file in the directory. E.g. If you are on linux calling `gitui -t arc.ron`, this will load the theme in `$XDG_CONFIG_HOME/gitui/arc.ron` or `$HOME/.config/gitui/arc.ron`.

Example theme override:

```
(
selection_bg: Some(Blue),
selection_fg: Some(White),
)
```

Note that you need to wrap values in `Some` due to the way the overrides work (as of 0.23).

Notes:

Expand Down
4 changes: 1 addition & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,7 @@ fn main() -> Result<()> {
let key_config = KeyConfig::init()
.map_err(|e| eprintln!("KeyConfig loading error: {e}"))
.unwrap_or_default();
let theme = Theme::init(&cliargs.theme)
.map_err(|e| eprintln!("Theme loading error: {e}"))
.unwrap_or_default();
let theme = Theme::init(&cliargs.theme);

setup_terminal()?;
defer! {
Expand Down
109 changes: 67 additions & 42 deletions src/ui/style.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
use anyhow::Result;
use asyncgit::{DiffLineType, StatusItemType};
use ratatui::style::{Color, Modifier, Style};
use ron::{
de::from_bytes,
ser::{to_string_pretty, PrettyConfig},
};
use ron::ser::{to_string_pretty, PrettyConfig};
use serde::{Deserialize, Serialize};
use std::{
fs::{self, File},
io::{Read, Write},
path::PathBuf,
rc::Rc,
};
use std::{fs::File, io::Write, path::PathBuf, rc::Rc};
use struct_patch::Patch;

pub type SharedTheme = Rc<Theme>;

#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Patch)]
#[patch_derive(Serialize, Deserialize)]
pub struct Theme {
selected_tab: Color,
command_fg: Color,
Expand Down Expand Up @@ -261,44 +255,46 @@ impl Theme {
.bg(self.push_gauge_bg)
}

// This will only be called when theme.ron doesn't already exists
fn save(&self, theme_file: &PathBuf) -> Result<()> {
let mut file = File::create(theme_file)?;
let data = to_string_pretty(self, PrettyConfig::default())?;
fn load_patch(theme_path: &PathBuf) -> Result<ThemePatch> {
let file = File::open(theme_path)?;

Ok(ron::de::from_reader(file)?)
}

fn load_old_theme(theme_path: &PathBuf) -> Result<Self> {
let old_file = File::open(theme_path)?;

Ok(ron::de::from_reader::<File, Self>(old_file)?)
}

// This is supposed to be called when theme.ron doesn't already exists.
fn save_patch(&self, theme_path: &PathBuf) -> Result<()> {
let mut file = File::create(theme_path)?;
let patch = self.into_patch_by_diff(Self::default());
let data = to_string_pretty(&patch, PrettyConfig::default())?;

file.write_all(data.as_bytes())?;

Ok(())
}

fn read_file(theme_file: PathBuf) -> Result<Self> {
let mut f = File::open(theme_file)?;
let mut buffer = Vec::new();
f.read_to_end(&mut buffer)?;
Ok(from_bytes(&buffer)?)
}
pub fn init(theme_path: &PathBuf) -> Self {
let mut theme = Self::default();

if let Ok(patch) = Self::load_patch(theme_path) {
theme.apply(patch);
} else if let Ok(old_theme) = Self::load_old_theme(theme_path)
{
theme = old_theme;

pub fn init(file: &PathBuf) -> Result<Self> {
if file.exists() {
match Self::read_file(file.clone()) {
Err(e) => {
let config_path = file.clone();
let config_path_old =
format!("{}.old", file.to_string_lossy());
fs::rename(
config_path.clone(),
config_path_old.clone(),
)?;

Self::default().save(file)?;

Err(anyhow::anyhow!("{}\n Old file was renamed to {:?}.\n Defaults loaded and saved as {:?}",
e,config_path_old,config_path.to_string_lossy()))
}
Ok(res) => Ok(res),
if theme.save_patch(theme_path).is_ok() {
log::info!("Converted old theme to new format.");
} else {
log::warn!("Failed to save theme in new format.");
}
} else {
Self::default().save(file)?;
Ok(Self::default())
}

theme
}
}

Expand Down Expand Up @@ -329,3 +325,32 @@ impl Default for Theme {
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
use std::io::Write;
use tempfile::NamedTempFile;

#[test]
fn test_smoke() {
let mut file = NamedTempFile::new().unwrap();

writeln!(
file,
r"
(
selection_bg: Some(White),
)
"
)
.unwrap();

let theme = Theme::init(&file.path().to_path_buf());

assert_eq!(theme.selection_fg, Theme::default().selection_fg);
assert_eq!(theme.selection_bg, Color::White);
extrawurst marked this conversation as resolved.
Show resolved Hide resolved
assert_ne!(theme.selection_bg, Theme::default().selection_bg);
}
}